一个线程送水,一个线程出水:多个线程操作同一个资源,但操作的动作不同。两个线程操作同一资源,但操作的动作不一样。两个方法
packagecn.itcast.day5.thread;//一进一出
public class线程通信
{public static voidmain(String[] args)
{
Resouce resouce= newResouce();
Input input= newInput(resouce);
OutPut outPut= newOutPut(resouce);
Thread thread1= newThread(input);
Thread thread2= newThread(outPut);
thread1.start();
thread2.start();
}
}classResouce
{publicString name;publicString sex;
}class Input implementsRunnable
{
Resouce resouce;
Input(Resouce resouce)
{this.resouce =resouce;
}
@Overridepublic voidrun()
{int x = 1;while (true)
{synchronized (Input.class)//两个线程的锁只要是一个object 在内存中的字节码
{if (x == 0)
{
resouce.name= "peter.peng";
resouce.sex= "boy";
}else{
resouce.name= "彭运松";
resouce.sex= "男";
}
x= (x + 1) % 2;
}
}
}
}class OutPut implementsRunnable
{
Resouce resouce;
OutPut(Resouce resouce)
{this.resouce =resouce;
}
@Overridepublic voidrun()
{while (true)
{synchronized (Input.class) //两个线程的锁只要是一个object 在内存中的字节码
{
System.out.println(Thread.currentThread()+ "-----:" + resouce.name + ":" +resouce.sex);
}
}
}
}
进水与进水的案例
如果要达到一进一去,交替出现而不是从上一案例一样,则得用到 wait() notify() notityAll(),理解这几个意义
1 packagecn.itcast.day5.thread;2
3 //一进一出
4 public class线程通信5 {6 public static voidmain(String[] args)7 {8 Resouce resouce = newResouce();9 Input input = newInput(resouce);10 OutPut outPut = newOutPut(resouce);11
12 Thread thread1 = newThread(input);13 Thread thread2 = newThread(outPut);14
15 thread1.start();16 thread2.start();17 }18 }19
20 classResouce21 {22 publicString name;23 publicString sex;24 boolean flag=false;25 }26
27 class Input implementsRunnable28 {29 Resouce resouce;30
31 Input(Resouce resouce)32 {33 this.resouce =resouce;34 }35
36 @Override37 public voidrun()38 {39 int x = 0;40 while (true)41 {42 synchronized (resouce)//两个线程的锁只要是一个object 在内存中的字节码
43 {44 if(resouce.flag)45 try
46 {47 wait();48 //由于第一次flag=false 所以线程1不会等待,就会执行x==0,赋一次值,赋值完后,flag=true,这时线程149 //就会等待,同是叫醒线程2.50 //由于flag=true 则线程2不会等待,就会执行输出语句,输出完后,flag=false,这时线程2就会等待,同时叫醒线程151 //这时就会执行else语句给resource第二次赋值,赋完值后x=(x+1)%2,这里x=0,同时flag=true,线程1又等待。同时52 //第二次叫醒线程2 .............
53 }54 catch(Exception e)55 {56 }57 if (x == 0)58 {59 resouce.name = "peter.peng";60 resouce.sex = "boy";61 } else
62 {63 resouce.name = "彭运松";64 resouce.sex = "男";65 }66 x = (x + 1) % 2;67 resouce.flag = true;68 resouce.notify();//叫醒线程2
69 }70 }71 }72
73 }74
75 class OutPut implementsRunnable76 {77 Resouce resouce;78
79 OutPut(Resouce resouce)80 {81 this.resouce =resouce;82 }83
84 @Override85 public voidrun()86 {87 while (true)88 {89 synchronized (resouce) //两个线程的锁只要是一个object 在内存中的字节码
90 {91 if (!resouce.flag)92 try
93 {94 resouce.wait();95 }96 catch(Exception e)97 {98
99 }100 System.out.println(resouce.name + ":" +resouce.sex);101 resouce.flag = false;102 resouce.notify();//叫醒线程1
103 }104 }105 }106 }
多张程交替打印两个人名
对等待线程的优化(上一程序) 对Resurce进行封装,并把set get 方法进行同步。
生者消费者的例子
1 packagenet.nw.entites;2
3 public classThreadDemo_Product_Customer {4
5 public static voidmain(String[] args) {6
7 Resource resource = newResource();8 Product product = newProduct(resource);9 Customer customer = newCustomer(resource);10
11 Thread t1 = newThread(product);12 Thread t2 = newThread(customer);13 Thread t3 = newThread(product);14 Thread t4 = newThread(customer);15
16 t1.start();17 t2.start();18 t3.start();19 t4.start();20 }21 }22
23 classResource {24 publicString name;25 public booleanflag;26 public int count = 0;27
28 public synchronized voidSet(String name) {29 while (true) {30 while(flag) {31 try{32 wait();33 } catch(Exception e) {34 e.printStackTrace();35 }36 }37 this.name = name + count++;38 System.out.println(Thread.currentThread().getName() + "-P:"
39 + this.name);40 flag = true;41 notifyAll();42 }43 }44
45 public synchronized voidgetOut() {46 while (true) {47 while (!flag) {48 try{49 wait();50 } catch(Exception e) {51 e.printStackTrace();52 }53 }54 System.out.println(Thread.currentThread().getName() + "-C:"
55 + this.name);56 flag = false;57 notifyAll();58 }59 }60 }61
62 class Product implementsRunnable {63 Resource resource;64
65 Product(Resource resource) {66 this.resource =resource;67 }68
69 @Override70 public voidrun() {71 resource.Set("pc");72 }73 }74
75 class Customer implementsRunnable {76 Resource resource;77
78 Customer(Resource resource) {79 this.resource =resource;80 }81
82 @Override83 public voidrun() {84 resource.getOut();85 }86
87 }
两个以上线程的消费与生产关系
JdK1.5 新特性的多线程操作
1 packagenet.nw.entites;2
3 importjava.util.concurrent.locks.Condition;4 importjava.util.concurrent.locks.Lock;5 importjava.util.concurrent.locks.ReentrantLock;6
7 public classThreadDemo_Product_Customer {8
9 public static voidmain(String[] args) {10
11 Resource resource = newResource();12 Product product = newProduct(resource);13 Customer customer = newCustomer(resource);14
15 Thread t1 = newThread(product);16 Thread t2 = newThread(customer);17 Thread t3 = newThread(product);18 Thread t4 = newThread(customer);19
20 t1.start();21 t2.start();22 t3.start();23 t4.start();24 }25 }26
27 classResource {28 publicString name;29 public booleanflag;30 public int count = 0;31
32 final Lock lock = newReentrantLock();33 final Condition notFull =lock.newCondition();34 final Condition notEmpty =lock.newCondition();35
36 public voidSet(String name) {37 lock.lock();38 try{39 while (true) {40 while(flag) {41 try{42 notFull.await();43 } catch(Exception e) {44 e.printStackTrace();45 }46 }47 this.name = name + count++;48 System.out.println(Thread.currentThread().getName() + "-P:"
49 + this.name);50 flag = true;51 notEmpty.signal();52 }53 } finally{54 lock.unlock();55 }56 }57
58 public voidgetOut() {59 lock.lock();60 try{61 while (true) {62 while (!flag) {63 try{64 notEmpty.await();65 } catch(Exception e) {66 e.printStackTrace();67 }68 }69 System.out.println(Thread.currentThread().getName() + "-C:"
70 + this.name);71 flag = false;72 notFull.signal();73 }74 } finally{75 lock.unlock();76 }77 }78 }79
80 class Product implementsRunnable {81 Resource resource;82
83 Product(Resource resource) {84 this.resource =resource;85 }86
87 @Override88 public voidrun() {89 resource.Set("pc");90 }91 }92
93 class Customer implementsRunnable {94 Resource resource;95
96 Customer(Resource resource) {97 this.resource =resource;98 }99
100 @Override101 public voidrun() {102 resource.getOut();103 }104
105 }
两个以上线程的生产与消费关系
说明:Lock提供更为优秀的方法来替换synchronized lock.lock lock.unlock(放在finally)
await single singleall 分别对应 wait notify notifyAll ,但JDK1.5后提供了codition,可以为生产消费指这不同的codition,这样两个线程或是两个以上线程就可以分开出来控制
如果是同一个codition singleAll时就会呼醒其它的线程同时也可以是同类的线程,达不到控制的效果。
线程的中断:其实只要控制住run方法的循环条件就可以了,但有一种情况下await()时就没有办法做了,因为根本就不会执行循环体的语句,这时要用到interruput,使线程势抛出一个异常InterruptedException,然后在验证循环体的条件。
1 packagenet.nw.entites;2
3 importjava.util.concurrent.locks.Condition;4 importjava.util.concurrent.locks.Lock;5 importjava.util.concurrent.locks.ReentrantLock;6
7 public classThreadDemo_Product_Customer {8
9 public static voidmain(String[] args) {10
11 Resource resource = newResource();12 Product product = newProduct(resource);13 Customer customer = newCustomer(resource);14
15 Thread t1 = newThread(product);16 Thread t2 = newThread(customer);17 Thread t3 = newThread(product);18 Thread t4 = newThread(customer);19 t1.start();20 t2.start();21
22 //t3.start();23 //t4.start();
24 }25 }26
27 classResource {28 publicString name;29 public booleanflag;30 public boolean conditionFlag = true;31 public int count = 0;32
33 final Lock lock = newReentrantLock();34 final Condition notFull =lock.newCondition();35 final Condition notEmpty =lock.newCondition();36
37 public voidSet(String name) {38
39 lock.lock();40 try{41 while(conditionFlag) {42 while(flag) {43 try{44 notFull.await();45 Thread.currentThread().interrupt();//把当前的线程中断了。
46 } catch(InterruptedException e) {47 conditionFlag = false;48 }49 }50 this.name = name + count++;51 System.out.println(Thread.currentThread().getName() + "-P:"
52 + this.name);53 flag = true;54 notEmpty.signal();55 }56 } finally{57 lock.unlock();58 if(Thread.interrupted()) {59 System.out.println(Thread.currentThread().getName()60 + ":线程中断了。。。。。。。。。。。");61 }62 }63 }64
65 public voidgetOut() {66
67 lock.lock();68 try{69 while(conditionFlag) {70 while (!flag) {71 try{72 notEmpty.await();73 Thread.currentThread().interrupt();//把当前的线程中断了。
74 } catch(InterruptedException e) {75 conditionFlag = false;76 }77 }78 System.out.println(Thread.currentThread().getName() + "-C:"
79 + this.name);80 flag = false;81 notFull.signal();82 }83 } finally{84 lock.unlock();85 if(Thread.interrupted()) {86 System.out.println(Thread.currentThread().getName()87 + ":线程中断了。。。。。。。。。。。");88 }89 }90 }91 }92
93 class Product implementsRunnable {94 Resource resource;95
96 Product(Resource resource) {97 this.resource =resource;98 }99
100 @Override101 public voidrun() {102 resource.Set("pc");103 }104 }105
106 class Customer implementsRunnable {107 Resource resource;108
109 Customer(Resource resource) {110 this.resource =resource;111 }112
113 @Override114 public voidrun() {115 resource.getOut();116 }117
118 }
多线程安全通信的线程中断
线程的join setDaemon yield
1 packagecn.itcast.day5.thread;2
3 class Demo1 implementsRunnable4 {5 private int count = 100;6
7 @Override8 public voidrun()9 {10 while (count > 0)11 {12 System.out.println(Thread.currentThread().getName() + ":" + "------peter.peng" + count--);13 Thread.yield();14 }15 }16 }17
18 public classThreadJionYield19 {20 public static void main(String[] args) throwsInterruptedException21 {22 //SetDaemon();//设为后台线程23 //ThreadJoin();//join可以用来时加入线程,遇到一个线程的Join主线程冻结,其它的不变,只到Join这个线程结束,主线程再执行。24 //SetPriority();//设置线程的优势级
25 Thread thread1 = new Thread(new Demo1());//yield让当前线程停止执行另一个线程。
26 Thread thread2 = new Thread(newDemo1());27
28 thread1.start();29 thread2.start();30 }31
32 private static voidSetPriority()33 {34 Thread thread1 = new Thread(newRunnable()35 {36 int count = 100;37
38 public voidrun()39 {40 while (count > 0)41 {42 System.out.println(Thread.currentThread().toString() + "------peter.peng" + count--);43 }44 }45 });46
47 Thread thread2 = new Thread(newRunnable()48 {49 int count = 100;50
51 public voidrun()52 {53 while (count > 0)54 {55 System.out.println(Thread.currentThread().toString() + "------peter.peng" + count--);56 }57 }58 });59
60 thread1.start();61 thread1.setPriority(Thread.MAX_PRIORITY);//设线程的优化级
62 thread2.start();63
64 System.out.println(Thread.currentThread().toString());65 }66
67 private static void ThreadJoin() throwsInterruptedException68 {69 Thread thread1 = new Thread(newRunnable()70 {71 int count = 100;72
73 public voidrun()74 {75 while (count > 0)76 {77 System.out.println(Thread.currentThread() + "------peter.peng" + count--);78 }79 }80 });81
82 Thread thread2 = new Thread(newRunnable()83 {84 int count = 100;85
86 public voidrun()87 {88 while (count > 0)89 {90 System.out.println(Thread.currentThread() + "------peter.peng" + count--);91 }92 }93 });94
95 thread1.start();96 //thread1.join();//说明thread1要主线程的执行权,这个时候主线程就会冻结了,只到它不要了才会给主线程,如果把它放在后面来执行
97 thread2.start();98 thread1.join();//这时thread1 与thread2交才替出现,只到结束才执行主线程的方法。
99
100 System.out.println(Thread.currentThread() + ":main");101 }102
103 private static voidSetDaemon()104 {105 Thread thread1 = new Thread(newRunnable()106 {107 int count = 0;108
109 public voidrun()110 {111 while (true)112 {113 System.out.println("------peter.peng" + count++);114 }115 }116 });117
118 Thread thread2 = new Thread(newRunnable()119 {120 int count = 0;121
122 public voidrun()123 {124 while (true)125 {126 System.out.println("------peter.peng" + count++);127 }128 }129 });130 thread1.setDaemon(true);//设为后台线程
131 thread2.setDaemon(true);//设为后台线程
132 thread1.start();133 thread2.start();134 System.out.println("over");135 }136 }
线程的Join,setDaemon yield