1. 程式人生 > >java 執行緒通訊的兩種方法

java 執行緒通訊的兩種方法

先講如何通訊: 再講 如何 同步。網上的程式碼是有問題的。我註釋了出來。

第一 。\執行緒 共用 一個 稀缺變數:

1、 繼承至 thread 類

public class Innersharethread { public static void main(String[] args) { Mythread mythread =new Mythread(); mythread.getThread().start(); mythread.getThread().start(); mythread.getThread().start(); mythread.getThread().start();
} } class Mythread { int index = 0; private class InnerThread extends Thread { public synchronized void run() {  //這是不同步的!!!這裡的synchronized 加不加 結果都不能同步,因為加的位置不對。同步請見後面。
//執行緒很隨意的就可以拿到index;
while (true) { System.out.println(Thread.currentThread().getName() + "is running and index is "+ index++); } }
} public Thread getThread() { return new InnerThread(); } }

2、通過實現Runnable介面實現執行緒的共享變數

public class Interfacaesharethread { public static void main(String[] args) { Mythread mythread =new Mythread(); new Thread(mythread).start(); new Thread(mythread).start(); new Thread(mythread).start(); new
Thread(mythread).start(); } } /* 實現Runnable介面 */ class Mythread implements Runnable { int index = 0; public synchronized void run() {//這是不同步的!!這裡加上 synchronized 就便成只有0號執行緒再跑了,其他的都沒法獲得資源。
//可是如果不加,大家都可以隨意搶奪index,無法同步
while (true) System.out.println(Thread.currentThread().getName() + "is running and the index is " + index++); } }

第二種,通過pipe 的方式,這種方式只能一個負責輸出,一個負責接收。這樣單向的。

public class CommunicateWhitPiping { public static void main(String[] args) { /** * 建立管道輸出流 */ PipedOutputStream pos =new PipedOutputStream(); /** * 建立管道輸入流 */ PipedInputStream pis =new PipedInputStream(); try { /** * 將管道輸入流與輸出流連線 此過程也可通過過載的建構函式來實現 */ pos.connect(pis); } catch(IOException e) { e.printStackTrace(); } /** * 建立生產者執行緒 */ Producer p = new Producer(pos); /** * 建立消費者執行緒 */ Consum c = new Consum(pis); /** * 啟動執行緒 */ p.start(); c.start(); } } /** * 生產者執行緒(與一個管道輸入流相關聯) * */ class Producer extends Thread { private PipedOutputStream pos; public Producer(PipedOutputStream pos) { this.pos = pos; } public void run() { int i = 8; try { pos.write(i); } catch(IOException e) { e.printStackTrace(); } } } /** * 消費者執行緒(與一個管道輸入流相關聯) * */ class Consum extends Thread { private PipedInputStream pis; public Consum(PipedInputStream pis) { this.pis = pis; } public void run() { try { System.out.println(pis.read()); } catch(IOException e) { e.printStackTrace(); } } }

這樣兩種方式搞定了。後面會再寫一篇socket 來實現多執行緒程式設計 和 python 在多執行緒上的實現。

第一例子:

1、相當於執行緒的工廠創造了四個相同的操作程式碼塊,在每個執行緒自己私有空間裡,所以加不加 synchronized (鎖) 根本沒用。

這裡的想法是要鎖住 稀缺資源 index;

2、synchronized 關鍵字不能加在 while 之外, 因為 加在那裡,while沒執行完畢,執行緒是不會放棄鎖的。

正確的做法:

public class Innersharethread { public static void main(String[] args) { Mythread mythread =new Mythread(); mythread.getThread().start(); mythread.getThread().start(); mythread.getThread().start(); mythread.getThread().start(); } } class Mythread { int index = 0; private class InnerThread extends Thread { public void run() { 
while (true) {
synchronized (MyThread.this){//獲得這個整個物件的鎖
System.out.println(Thread.currentThread().getName() + "is running and index is "+ index++);
}
} } } public Thread getThread() { return new InnerThread(); } }

或者用 synchronized 鎖住 爭用資源的語句塊。

如下,也是可行的:

public class Innersharethread { public static void main(String[] args) { Mythread mythread =new Mythread(); mythread.getThread().start(); mythread.getThread().start(); mythread.getThread().start(); mythread.getThread().start(); } } class Mythread {

int index = 0;

public synchronized int add(){
  return index++; // 鎖住爭用資源的語句塊。
}

private class InnerThread extends Thread { public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + "is running and index is "+ add());
} } } public Thread getThread() { return new InnerThread(); } }

ok,後面的 runnable 的介面的更改方式我就直接給出答案了。也是一樣的。

public class Interfacaesharethread { public static void main(String[] args) { Mythread mythread =new Mythread(); new Thread(mythread).start(); new Thread(mythread).start(); new Thread(mythread).start(); new Thread(mythread).start(); } } /* 實現Runnable介面 */ class Mythread implements Runnable { int index = 0; public void run() {
while (true)
synchronized (this){ // 注意哈,這裡的是this 不用在加 (類名.this)的格式了,因為主要是為了鎖住稀缺資源,
//而第一例的實現是通過內部類來實現的,所以要拿到外部類的物件鎖才行。

System.out.println(Thread.currentThread().getName() + "is running and the index is " + index++);
}
} }


或者 :

class Mythread implements Runnable { int index = 0;

public synchronized int add(){
  return index++;
}

public void run() {
while (true)
System.out.println(Thread.currentThread().getName() + "is running and the index is " + add());
}
} }