方法wait的作用是使当前执行代码的线程进行等待,将当前线程置入预执行队列,在调用wait之前,线程必须获得该对象的对象级别锁,即只能在同步方法或者同步块中调用wait方法。
方法notify也要在同步方法或同步块中调用,
再执行notify方法后,要等到执行notify的方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁。
package com.java.mul;
import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;
public class multest {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
Object lock = new Object();
MyThreadA a = new MyThreadA(lock);
a.start();
Thread.sleep(3000);
MyThreadB b = new MyThreadB(lock);
b.start();
}
}
package com.java.mul;
public class MyThreadA extends Thread{
private Object lock;
public MyThreadA(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
try {
synchronized(lock) {
System.out.println("start " + System.currentTimeMillis());
lock.wait();
System.out.println("finish " + System.currentTimeMillis());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.java.mul;
public class MyThreadB extends Thread{
private Object lock;
public MyThreadB(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
synchronized(lock) {
System.out.println("start notify " + System.currentTimeMillis());
lock.notify();
System.out.println("finish notify" + System.currentTimeMillis());
}
}
}
package com.java.mul;
import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;
public class multest {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
Object lock = new Object();
MyThreadA a = new MyThreadA(lock);
a.start();
Thread.sleep(50);
MyThreadB b = new MyThreadB(lock);
b.start();
}
}
package com.java.mul;
public class MyThreadA extends Thread{
private Object lock;
public MyThreadA(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
try {
synchronized(lock) {
if(MyList.size() != 5) {
System.out.println("start " + System.currentTimeMillis());
lock.wait();
System.out.println("finish " + System.currentTimeMillis());
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.java.mul;
public class MyThreadB extends Thread{
private Object lock;
public MyThreadB(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
try {
synchronized(lock) {
for(int i = 0;i<10;i++) {
MyList.add();
if(MyList.size() == 5) {
lock.notify();
System.out.println("send notyfy ");
}
System.out.println("add " + (i + 1)+"elements");
}
Thread.sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.java.mul;
import java.util.ArrayList;
import java.util.List;
public class MyList {
private static List list = new ArrayList();
public static void add() {
list.add("sss");
}
public static int size() {
return list.size();
}
}
生产者消费者
package com.java.mul;
public class P {
private String lock;
public P(String lock) {
super();
this.lock = lock;
}
public void setValue() {
try {
synchronized(lock) {
if(!ValueObject.value.equals("")) {
lock.wait();
}
String value = System.currentTimeMillis() + "_" + System.nanoTime();
System.out.println("set is " + value);
ValueObject.value = value;
lock.notify();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.java.mul;
public class C {
private String lock;
public C(String lock) {
super();
this.lock = lock;
}
public void getValue() {
try {
synchronized(lock) {
if(ValueObject.value.equals("")) {
lock.wait();
}
System.out.println("get is " + ValueObject.value);
ValueObject.value = "";
lock.notify();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.java.mul;
public class ValueObject {
public static String value = "";
}
package com.java.mul;
public class ThreadP extends Thread{
private P p;
public ThreadP(P p) {
super();
this.p = p;
}
@Override
public void run() {
while(true) {
p.setValue();
}
}
}
package com.java.mul;
public class ThreadC extends Thread{
private C c;
public ThreadC(C c) {
super();
this.c = c;
}
@Override
public void run() {
while(true) {
c.getValue();
}
}
}
package com.java.mul;
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
String lock = new String("");
P p = new P(lock);
C c = new C(lock);
ThreadP pThread = new ThreadP(p);
ThreadC cThread = new ThreadC(c);
pThread.start();
cThread.start();
}
}
当有多个生产者和消费者,生产者的notify有可能唤醒生产者,这样积少成多,容易造成假死。
一生产一消费
package com.java.mul;
import java.util.ArrayList;
import java.util.List;
public class MyStack {
private List list = new ArrayList();
synchronized public void push() {
try {
if(list.size() == 1) {
this.wait();
}
list.add("anyString=" + Math.random());
this.notify();
System.out.println("push=" + list.size());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized public String pop() {
String returnValue = "";
try {
if(list.size()==0) {
System.out.println("pop:"+ Thread.currentThread().getName() + " wait");
this.wait();
}
returnValue = "" + list.get(0);
list.remove(0);
this.notify();
System.out.println("pop="+list.size());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return returnValue;
}
}
package com.java.mul;
public class ThreadC extends Thread{
private C c;
public ThreadC(C c) {
super();
this.c = c;
}
@Override
public void run() {
while(true) {
c.popService();
}
}
}
package com.java.mul;
public class ThreadP extends Thread{
private P p;
public ThreadP(P p) {
super();
this.p = p;
}
@Override
public void run() {
while(true) {
p.pushService();
}
}
}
package com.java.mul;
public class P {
private MyStack myStack;
public P(MyStack myStack) {
super();
this.myStack = myStack;
}
public void pushService() {
myStack.push();
}
}
package com.java.mul;
public class C {
private MyStack myStack;
public C(MyStack myStack) {
super();
this.myStack = myStack;
}
public void popService() {
System.out.println("pop=" + myStack.pop());
}
}
package com.java.mul;
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyStack myStack = new MyStack();
P p = new P(myStack);
C c = new C(myStack);
ThreadP pThread = new ThreadP(p);
ThreadC cThread = new ThreadC(c);
pThread.start();
cThread.start();
}
}
一生产多消费(要把if换成while,来防止一个pop被唤醒,但是listsize为0,但是这时候也可能会发生假死)
package com.java.mul;
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyStack myStack = new MyStack();
P p = new P(myStack);
C c1 = new C(myStack);
C c2 = new C(myStack);
C c3 = new C(myStack);
C c4 = new C(myStack);
ThreadP pThread = new ThreadP(p);
pThread.start();
ThreadC cThread1 = new ThreadC(c1);
ThreadC cThread2 = new ThreadC(c2);
ThreadC cThread3 = new ThreadC(c3);
ThreadC cThread4 = new ThreadC(c4);
cThread1.start();
cThread2.start();
cThread3.start();
cThread4.start();
}
}
package com.java.mul;
import java.util.ArrayList;
import java.util.List;
public class MyStack {
private List list = new ArrayList();
synchronized public void push() {
try {
while(list.size() == 1) {
this.wait();
}
list.add("anyString=" + Math.random());
this.notify();
System.out.println("push=" + list.size());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized public String pop() {
String returnValue = "";
try {
while(list.size()==0) {
System.out.println("pop:"+ Thread.currentThread().getName() + " wait");
this.wait();
}
returnValue = "" + list.get(0);
list.remove(0);
this.notify();
System.out.println("pop="+list.size());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return returnValue;
}
}
通过管道进行线程间通信:字节流
java的JDK中提供了4个类来使线程间可以进行通信:
PipedInputStreeam和PipedOutputStreeam
PipedReader和PipedWriter
实战:等待/通知之交叉备份
package com.java.mul;
public class DBTools {
volatile private boolean prevIsA = false;
synchronized public void backupA(){
try {
while(prevIsA == true) {
wait();
}
for(int i=0;i<5;i++) {
System.out.println("-----");
}
prevIsA = true;
notifyAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized public void backupB(){
try {
while(prevIsA == false) {
wait();
}
for(int i=0;i<5;i++) {
System.out.println("22222");
}
prevIsA = false;
notifyAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.java.mul;
public class BackupA extends Thread{
private DBTools dbtools;
public BackupA(DBTools dbtools) {
super();
this.dbtools = dbtools;
}
@Override
public void run() {
dbtools.backupA();
}
}
package com.java.mul;
public class BackupB extends Thread{
private DBTools dbtools;
public BackupB(DBTools dbtools) {
super();
this.dbtools = dbtools;
}
@Override
public void run() {
dbtools.backupB();
}
}
package com.java.mul;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
DBTools dbtools = new DBTools();
for(int i = 0;i<20;i++) {
BackupB output = new BackupB(dbtools);
output.start();
BackupA input = new BackupA(dbtools);
input.start();
}
}
}
方法join的使用(等待线程对象销毁)
join在内部使用wait方法进行等待,synchronized关键字使用的是“对象监视器”原理作为同步。
方法join后的代码可能异步提前运行,造成多种结果的组合。
类ThreadLocal的使用(使每一个线程都有一个自己的共享变量的值,也就是变量在不同线程的隔离性)
package com.java.mul;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
MyThreadA a = new MyThreadA();
MyThreadB b = new MyThreadB();
a.start();
b.start();
for(int i = 0;i<100;i++) {
Tools.t1.set("Main" + (1 + i));
System.out.println("Main get Value=" + Tools.t1.get());
Thread.sleep(200);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.java.mul;
public class Tools {
public static ThreadLocal t1 = new ThreadLocal();
}
package com.java.mul;
public class MyThreadA extends Thread{
@Override
public void run() {
try {
for(int i = 0;i<100;i++) {
Tools.t1.set("ThreadA" + (1 + i));
System.out.println("ThreadA get Value=" + Tools.t1.get());
Thread.sleep(200);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.java.mul;
public class MyThreadB extends Thread{
@Override
public void run() {
try {
for(int i = 0;i<100;i++) {
Tools.t1.set("ThreadB" + (1 + i));
System.out.println("ThreadB get Value=" + Tools.t1.get());
Thread.sleep(200);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
InheritableThreadLocal(使用这个类,可以使子线程继承父线程的值)