1.文字檔案複製
/*
將C盤下的一個文字檔案複製到D盤下。
其實就是將C盤下的檔案資料儲存到D盤下的一個檔案中
步驟:
1.在D盤中建立一個檔案,用於儲存C盤檔案中的資料。
2.定義讀取流和C盤檔案關聯
3.通過不斷的讀寫完成資料儲存。
4.關閉資源。
*/
//方法一
import java.io.*;
class CopyText {
public static void main(String[] args) throws IOException{
copy();
}
public static void copy(){
FileReader fr = null;
FileWriter fw = null;
try{
fr = new FileReader("c:\\demo.txt");
fw = new FileWriter("d:\\demoD.txt",true);
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);
}
}catch (IOException e){
throw new RuntimeException("讀寫失敗");
}finally{
if(fr!=null)
try{
fr.close();
}catch (IOException e){
System.out.println(e.toString());
}
if(fw!=null)
try{
fw.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
}
}
//方法二
/*
通過緩衝區複製一個文字檔案。
*/
import java.io.*;
class CopyTextByBuf{
public static void main(String[] args){
BufferedWriter bufw = null;
BufferedReader bufr = null;
try
{
bufw = new BufferedWriter(new FileWriter("e:\\bufD.txt",true));
bufr = new BufferedReader(new FileReader("c:\\buf.txt"));
String line = null;//相當於中轉站。
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
catch (IOException e)
{
throw new RuntimeException("讀寫失敗");
}
finally
{
if(bufw!=null)
try
{
bufw.close();
}
catch (IOException e)
{
throw new RuntimeException("寫入關閉失敗");
}
if(bufr!=null)
try
{
bufr.close();
}
catch (IOException e)
{
throw new RuntimeException("讀取關閉失敗");
}
}
}
}
2.二進位制檔案(圖片,視訊等)複製
/*
複製一個圖片(不要拿字元流處理媒體檔案,字元流只處理文字資料)
思路:
1.用位元組讀取流物件和圖片關聯
2.用位元組寫入流物件建立一個圖片檔案,用於儲存獲取到的圖片資料。
3.通過迴圈讀寫,完成資料的儲存
4.關閉資源。
*/
import java.io.*;
class CopyPic
{
public static void main(String[] args)
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
fos = new FileOutputStream("CopyofSrc.png");
fis = new FileInputStream("src.jpg");
byte[] buf = new byte[fis.available()];//定義一個剛剛好的緩衝區,不用再迴圈了。
int len = 0;
while((len = fis.read(buf))!=-1)
{
fos.write(buf);
}
}
catch (IOException e)
{
throw new RuntimeException("讀寫失敗");
}
finally
{
try
{
if(fos!=null)
fos.close();
}
catch (IOException e)
{
throw new RuntimeException("寫入失敗");
}
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
throw new RuntimeException("讀取失敗");
}
}
}
}
3.標準鍵盤讀取/標準控制檯輸出
//讀取鍵盤輸入的最常見寫法。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//寫入控制檯的最常用寫法。
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
4.UDP
/*
編寫一個聊天程式
有收資料的部分和發資料的部分
這兩部分需要同時執行,那就需要用到多執行緒技術,
一個執行緒控制接收,一個執行緒控制傳送。
因為收和發動作是不一致的,所以要定義兩個run方法,
而且這兩個方法要封裝到不同的類中。
*/
import java.io.*;
import java.net.*;
class Send implements Runnable
{
private DatagramSocket ds ;
public Send(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = bufr.readLine())!= null)
{
if("886".equals(line))
break;
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10003);
ds.send(dp);
}
}
catch (Exception e)
{
throw new RuntimeException("傳送端失敗");
}
}
}
class Rece implements Runnable
{
private DatagramSocket ds ;
public Rece(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
while(true)
{
byte[] buf = new byte[1024*64];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+data);
}
}
catch (Exception e)
{
throw new RuntimeException("接收端失敗");
}
}
}
class ChatDemo //必須掌握
{
public static void main(String[] args) throws Exception
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10003);
new Thread(new Send(sendSocket)).start();
new Thread(new Rece(receSocket)).start();
}
}
5.TCP
/*
需求:客戶端併發上傳圖片
*/
/*
客戶端
1.服務端點
2.讀取客戶端已有的圖片資料
3.通過socket輸出流將資料發給服務端
4.讀取服務端反饋資訊
5.關閉
*/
import java.io.*;
import java.net.*;
class UploadPicClient
{
public static void main(String[] args) throws IOException
{
//主函式傳引數 java UploadPicClient c:\1.png
if(args.length!=1)
{
System.out.println("請選擇一個jpg格式的圖片檔案");
return;
}
File file = new File(args[0]);
if(!(file.exists()&&file.isFile()))
{
System.out.println("上傳的檔案不存在或者不是檔案");
return ;
}
if(!(file.getName().endsWith(".png")))
{
System.out.println("上傳的檔案格式不正確,請重新選擇!");
return;
}
if(file.length()>1024*1024*5)
{
System.out.println("檔案過大,不安好心,重新選擇 !");
return;
}
Socket s = new Socket("localhost",50005);
FileInputStream in = new FileInputStream(file);
OutputStream out = s.getOutputStream();
byte[] buf = new byte[1024];
int len = 0 ;
while((len = in.read(buf))!=-1)
{
out.write(buf,0,len);
}
//告訴伺服器資料寫完了。
s.shutdownOutput();
InputStream is = s.getInputStream();
byte[] bufIn = new byte[1024];
int num = is.read(bufIn);
System.out.println(new String(bufIn,0,num));
s.close();
in.close();
}
}
/*
服務端
這個服務端有個侷限性,當A客戶端連線上以後,被服務端獲取到,服務端執行具體流程。
這時B客戶端連線,只有等待
因為服務端還沒有處理完A客戶端的請求,還要迴圈回來執行下次accept方法,所以
暫時獲取不到B客戶端物件。
那麼為了可以讓多個客戶端同時併發訪問服務端,
那麼服務端最好就是將每個客戶端封裝到一個單獨的執行緒中,這樣,就可以
同時處理多個客戶端請求。
如何定義執行緒呢?
只要明確了每一個客戶端要在服務端執行的程式碼即可,將該程式碼存入run方法中。
*/
class PicThread implements Runnable
{
private Socket s ;
PicThread(Socket s )
{
this.s = s;
}
public void run()
{
String ip = s.getInetAddress().getHostAddress();
int num = 1;//只能定義在函式內,在外的話是共享資料,不行的。
try
{
System.out.println(ip+".....connected");
InputStream in = s.getInputStream();
File file = new File("d:\\server.png");
while(file.exists())
file = new File("d:\\server("+(num++)+").png");
FileOutputStream out = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len = 0 ;
while((len = in.read(buf))!=-1)
{
out.write(buf,0,len);
}
OutputStream os = s.getOutputStream();
os.write("上傳圖片成功!!".getBytes());
out.close();
s.close();
}
catch (Exception e)
{
throw new RuntimeException(ip+"上傳失敗^_^");
}
}
}
class UploadPicServer
{
public static void main(String[] args) throws IOException
{
ServerSocket ss = new ServerSocket(50005);
while(true)
{
Socket s = ss.accept();
new Thread(new PicThread(s)).start();//伺服器多執行緒玩法,幾乎所有伺服器都這麼玩。
}
}
}
6.多執行緒實現方式
//方法一:
/*
建立兩個執行緒,和主執行緒交替執行
執行緒都有自己預設的名稱
Thread-編號 該編號從0開始
static Thread currentThread():獲取當前執行緒物件。
getName():獲取執行緒名稱。
設定執行緒名稱:setName或者通過建構函式
*/
class Test extends Thread
{
public Test(String name)
{
super(name);//通過建構函式給執行緒取名。
}
public void run(){
for(int x = 0;x <10;x++)
{
System.out.println((Thread.currentThread()==this)+"...."+this.getName()+"run..."+x);
}
}
}
class ThreadTest
{
public static void main(String[] args)
{
Test t1 = new Test("one----");
Test t2 = new Test("two++++");
t1.start();
t2.start();
for(int i = 0 ;i<20;i++)
System.out.println("hello world"+i);
}
}
//方法二
class Ticket implements Runnable
{
private int tick = 10;
public void run()
{
while(true)
{
if(tick>0)
{
System.out.println(Thread.currentThread().getName()+"sale:"+tick--);
}
}
}
}
class TicketDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
7.死鎖/執行緒間通訊
/*
死鎖程式經典案例。面試可以用
*/
class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(MyLock.locka)
{
System.out.println("if locka");
synchronized(MyLock.lockb)
{
System.out.println("if lockb");
}
}
}
}
else
{
while(true)
{
synchronized(MyLock.lockb)
{
System.out.println("else lockb");
synchronized(MyLock.locka)
{
System.out.println("else locka");
}
}
}
}
}
}
class MyLock
{
static Object locka = new Object();
static Object lockb = new Object();
}
class DeadLockTest
{
public static void main(String[] args)
{
Thread t1= new Thread(new Test(true));
Thread t2= new Thread(new Test(false));
t1.start();
t2.start();
}
}
/*
經典:面試用。
JDK1.5中提供了多執行緒升級解決方案
將同步synchronized替換成顯示的Lock操作
將Object中的wait,notify,notifyAll,替換了condition物件。
該物件可以通過Lock鎖進行獲取
該示例中,實現了本方只喚醒對方的操作。
*/
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public void set(String name)throws InterruptedException
{
lock.lock();
try
{
while(flag)
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生產者........."+this.name);
flag = true;
condition_con.signal();
}finally
{
lock.unlock();//釋放鎖的動作一定要執行,放在finally裡面
}
}
public void out()throws InterruptedException
{
lock.lock();
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消費者..."+this.name);
flag = false;
condition_pro.signal();
}finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.set("+商品+");
}
catch (InterruptedException e)
{
}
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.out();
}
catch (InterruptedException e)
{
}
}
}
}
/*
執行緒間通訊:
其實就是多個執行緒在操作同一個資源
但是操作的動作不同。
*/
class Res
{
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name,String sex)
{
this.name = name;
this.sex = sex;
}
public synchronized void out()
{
System.out.println(name+"....."+sex);
}
}
class Input implements Runnable
{
private Res r;
//Object obj = new Object();
Input(Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
//synchronized(Input.class) 只要在記憶體中是唯一的物件就行
synchronized(r)
{
if(r.flag)
try{r.wait();}catch(Exception e){}
if(x == 0)
{
r.name = "mike";
r.sex = "man";
}
else
{
r.name = "麗麗";
r.sex = "女";
}
x = (x+1)%2;
r.flag = true;
r.notify();
}
}
}
}
class Output implements Runnable
{
private Res r;
//Object obj = new Object();
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
//synchronized(Input.class) 只要在記憶體中是唯一的物件就行
synchronized(r)
{
if(!r.flag)
try{r.wait();}catch(Exception e){}
System.out.println(r.name+"..."+r.sex);
r.flag = false;
r.notify();
}
}
}
}
class InputOutput
{
public static void main(String[] args)
{
Res r = new Res();
Input in = new Input(r);
Output op = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(op);
t1.start();
t2.start();
}
}
/*
wait():
nofity():
notifyAll():
都使用在同步中,因為要對持有監視器(鎖)的執行緒操作。
所以要使用在同步中,因為只有同步才具有鎖。
為什麼這些操作執行緒的方法要定義在Object類中呢?
因為這些方法在操作同步中執行緒時,都必須要標識它們所操作執行緒持有的鎖,
只有同一個鎖上的被等待執行緒,可以被同一個鎖上的notify喚醒,
不可以對不同鎖中的執行緒進行喚醒。
也就是說,等待和喚醒必須是同一個鎖,而鎖可以是任意物件,所以
可以被任意物件呼叫的方法定義在Object類中。
*/