多线程间通信
总结以下通信方式:因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁。只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。
class Res { String name; String sex; boolean flag = false; } class Input implements Runnable { private Res r ; Input(Res r) { this.r = r; } public void run() { int x = 0; while(true) { 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 ; Output(Res r) { this.r = r; } public void run() { while(true) { synchronized(r) { if(!r.flag) try{r.wait();}catch(Exception e){} System.out.println(r.name+"...."+r.sex); r.flag = false; r.notify(); } } } } class Test { public static void main(String[] args) { Res r = new Res(); Input in = new Input(r); Output out = new Output(r); Thread t1 = new Thread(in); Thread t2 = new Thread(out); t1.start(); t2.start(); } }代码优化下:
class Res { private String name; private String sex; private boolean flag = false; public synchronized void set(String name,String sex) { if(flag) try{this.wait();}catch(Exception e){} this.name = name; this.sex = sex; flag = true; this.notify(); } public synchronized void out() { if(!flag) try{this.wait();}catch(Exception e){} System.out.println(name+"........"+sex); flag = false; this.notify(); } } class Input implements Runnable { private Res r ; Input(Res r) { this.r = r; } public void run() { int x = 0; while(true) { if(x==0) r.set("mike","man"); else r.set("丽丽","女女女女女"); x = (x+1)%2; } } } class Output implements Runnable { private Res r ; Output(Res r) { this.r = r; } public void run() { while(true) { r.out(); } } } class InputOutputDemo2 { public static void main(String[] args) { Res r = new Res(); new Thread(new Input(r)).start(); new Thread(new Output(r)).start(); }另一个示例:
class Test { public static void main(String[] args) { Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t1 = new Thread(pro); Thread t2 = new Thread(pro); Thread t3 = new Thread(con); Thread t4 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); } } class Resource { private String name; private int count = 1; private boolean flag = false; public synchronized void set(String name) { while(flag) try{this.wait();}catch(Exception e){} this.name = name+"--"+count++; System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name); flag = true; this.notifyAll(); } public synchronized void out() { while(!flag) try{wait();}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name); flag = false; this.notifyAll(); } } class Producer implements Runnable { private Resource res; Producer(Resource res) { this.res = res; } public void run() { while(true) { res.set("+商品+"); } } } class Consumer implements Runnable { private Resource res; Consumer(Resource res) { this.res = res; } public void run() { while(true) { res.out(); } } }对于多个生产者和消费者。
只有一种,run方法结束。
开启多线程运行,运行代码通常是循环结构。
只要控制住循环,就可以让run方法结束,也就是线程结束。
特殊情况:
当线程处于了冻结状态。
就不会读取到标记。那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。
Thread类提供该方法 interrupt();
class StopThread implements Runnable { private boolean flag =true; public synchronized void run() { while(flag) { try {wait();} catch(Exception e) { System.out.println(Thread.currentThread().getName()+"....Exception"); flag=false; } System.out.println(Thread.currentThread().getName()+"....run"); } } public void changeFlag() { flag = false; } } class Test { public static void main(String[] args) { StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.start(); t2.start(); int num = 0; while(true) { if(num++ == 60) { //st.changeFlag(); t1.interrupt(); t2.interrupt(); break; } System.out.println(Thread.currentThread().getName()+"......."+num); } System.out.println("over"); } }
setDaemon:将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
该方法必须在启动线程前调用。
package Test; class StopThread implements Runnable { private boolean flag =true; public synchronized void run() { while(flag) { try {wait();} catch(Exception e) { System.out.println(Thread.currentThread().getName()+"....Exception"); flag=false; } System.out.println(Thread.currentThread().getName()+"....run"); } } public void changeFlag() { flag = false; } } class Test { public static void main(String[] args) { StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.setDaemon(true); t2.setDaemon(true); t1.start(); t2.start(); int num = 0; while(true) { if(num++ == 60) { break; } System.out.println(Thread.currentThread().getName()+"......."+num); } System.out.println("over"); } }join:
class Demo implements Runnable { public void run() { for(int x=0; x<30; x++) { System.out.println(Thread.currentThread().getName()+"....."+x); } } } class Test { public static void main(String[] args) throws Exception { Demo d = new Demo(); Thread t1 = new Thread(d); Thread t2 = new Thread(d); t1.start(); t1.join(); t2.start(); for(int x=0; x<10; x++) { System.out.println("main....."+x); } System.out.println("over"); } }yield:
class Demo implements Runnable { public void run() { for(int x=0; x<30; x++) { System.out.println(Thread.currentThread().getName()+"....."+x); Thread.yield(); } } } class Test { public static void main(String[] args) throws Exception { Demo d = new Demo(); Thread t1 = new Thread(d); t1.start(); for(int x=0; x<10; x++) { System.out.println("main....."+x); } System.out.println("over"); } }