黑马程序员:Java基础总结----线程间通信
2013-06-27 19:11
651 查看
黑马程序员:Java基础总结
线程间通信
ASP.Net+Android+IO开发、.Net培训、期待与您交流!
线程间通信
其实就是多个线程在操作同一个资源,
但是操作的动作不同。
等待/唤醒机制
也就是常见的生产者消费者问题。
1.当多个生产者消费者出现时,
需要让获取执行权的线程判断标记。
通过while完成。
2.需要将对方的线程唤醒。
仅仅用notify,是不可以的。因为有可能出现只唤醒本方。
有可能会导致,所有线程都等待。
所以可以通过notifyAll的形式来完成 。
JDK1.5版本提供了一些新的对象,优化了等待唤醒机制。
1,将synchronized 替换成了Lock接口。
将隐式锁,升级成了显示锁。
Lock
获取锁:lock();
释放锁:unlock();注意:释放的动作一定要执行,所以通常定义在finally中。
获取Condition对象:newCondition();
2,将Object中的wait,notify,notifyAll方法都替换成了Condition的await,signal,signalAll。
和以前不同是:一个同步代码块具备一个锁,该所以具备自己的独立wait和notify方法。
现在是将wait,notify等方法,封装进一个特有的对象Condition,而一个Lock锁上可以有多个Condition对象。
[align=left]Lock lock = new ReentrantLock();[/align]
[align=left] Condition conA = lock.newCondition();[/align]
[align=left] Condition conB = lock.newCondition();[/align]
[align=left] con.await(); //生产,,消费[/align]
[align=left] con.signal();生产[/align]
[align=left] set()[/align]
[align=left] {[/align]
[align=left] if(flag)[/align]
[align=left] conA.await(); //生产者,[/align]
[align=left] code......;[/align]
[align=left] flag = true;[/align]
[align=left] conB.signal();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] out()[/align]
[align=left] {[/align]
[align=left] if(!flag)[/align]
[align=left] conB.await(); //消费者[/align]
[align=left] code....;[/align]
[align=left] flag = false;[/align]
[align=left] conA.signal();[/align]
[align=left] }[/align]
wait和sleep的区别:
wait:释放cpu执行权,释放同步中锁。
sleep:释放cpu执行权,不释放同步中锁。
synchronized(锁)
{
wait();
}
停止线程:
stop过时。
原理:run方法结束。run方法中通常定义循环,指定控制住循环线程即可结束。
1,定义结束标记。
2,当线程处于了冻结状态,没有执行标记,程序一样无法结束。
这时可以循环,正常退出冻结状态,或者强制结束冻结状态。
强制结束冻结状态:interrupt();目的是线程强制从冻结状态恢复到运行状态。
但是会发生InterruptedException异常。
线程中一些常见方法:
setDaemon(boolean):将线程标记为后台线程,后台线程和前台线程一样,开启,一样抢执行权运行,
只有在结束时,有区别,当前台线程都运行结束后,后台线程会自动结束。
join():什么意思?等待该线程结束。当A线程执行到了B的.join方法时,A就会处于冻结状态。
A什么时候运行呢?当B运行结束后,A就会具备运行资格,继续运行。
加入线程,可以完成对某个线程的临时加入执行。
唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个
直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。
此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者:
通过执行此对象的同步实例方法。
通过执行在此对象上进行同步的
对于
一次只能有一个线程拥有对象的监视器。
[align=left]class Res[/align]
[align=left]{[/align]
[align=left] private String name ;[/align]
[align=left] private String sex ;[/align]
[align=left] private boolean flag = false;[/align]
public synchronized void set(String
name,String sex)
[align=left] {[/align]
[align=left] if(flag )[/align]
try{this .wait();}catch(Exception
e){}
this.name =
name;
[align=left] [/align]
this.sex =
sex;
[align=left] flag = true ;[/align]
[align=left] this.notify();[/align]
[align=left] }[/align]
[align=left] public synchronized void out()[/align]
[align=left] {[/align]
[align=left] if(!flag )[/align]
try{this .wait();}catch(Exception
e){}
[align=left] System. out.println(name +"........" +sex );[/align]
[align=left] flag = false ;[/align]
[align=left] this.notify();[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]class Input implements Runnable[/align]
[align=left]{[/align]
[align=left] private Res r ;[/align]
[align=left] Input(Res r)[/align]
[align=left] {[/align]
this.r =
r;
[align=left] }[/align]
[align=left] public void run()[/align]
[align=left] {[/align]
int x
= 0;
[align=left] while(true )[/align]
[align=left] {[/align]
[align=left] if(x==0) [/align]
[align=left] r.set( "mike","man" ); [/align]
[align=left] else [/align]
[align=left] r.set( "丽丽","女女女女女" ); [/align]
[align=left] x = (x+1)%2;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]class Output implements Runnable[/align]
[align=left]{[/align]
[align=left] private Res r ;[/align]
[align=left] [/align]
[align=left] Output(Res r)[/align]
[align=left] {[/align]
this.r =
r;
[align=left] }[/align]
[align=left] public void run()[/align]
[align=left] {[/align]
[align=left] while(true )[/align]
[align=left] {[/align]
[align=left] r.out();[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]class InputOutputDemo2[/align]
[align=left]{[/align]
public static void main(String[]
args)
[align=left] {[/align]
[align=left] Res r = new Res();[/align]
[align=left] new Thread(new Input(r)).start();[/align]
[align=left] new Thread(new Output(r)).start();[/align]
[align=left] /*[/align]
[align=left] Input in = new Input(r);[/align]
[align=left] Output out = new Output(r);[/align]
[align=left] Thread t1 = new Thread(in);[/align]
[align=left] Thread t2 = new Thread(out);[/align]
[align=left] t1.start();[/align]
[align=left] t2.start();[/align]
[align=left] */[/align]
[align=left] }[/align]
[align=left]}[/align]
ASP.Net+Android+IO开发、.Net培训、期待与您交流!
线程间通信
ASP.Net+Android+IO开发、.Net培训、期待与您交流!
线程间通信
其实就是多个线程在操作同一个资源,
但是操作的动作不同。
等待/唤醒机制
也就是常见的生产者消费者问题。
1.当多个生产者消费者出现时,
需要让获取执行权的线程判断标记。
通过while完成。
2.需要将对方的线程唤醒。
仅仅用notify,是不可以的。因为有可能出现只唤醒本方。
有可能会导致,所有线程都等待。
所以可以通过notifyAll的形式来完成 。
JDK1.5版本提供了一些新的对象,优化了等待唤醒机制。
1,将synchronized 替换成了Lock接口。
将隐式锁,升级成了显示锁。
Lock
获取锁:lock();
释放锁:unlock();注意:释放的动作一定要执行,所以通常定义在finally中。
获取Condition对象:newCondition();
2,将Object中的wait,notify,notifyAll方法都替换成了Condition的await,signal,signalAll。
和以前不同是:一个同步代码块具备一个锁,该所以具备自己的独立wait和notify方法。
现在是将wait,notify等方法,封装进一个特有的对象Condition,而一个Lock锁上可以有多个Condition对象。
[align=left]Lock lock = new ReentrantLock();[/align]
[align=left] Condition conA = lock.newCondition();[/align]
[align=left] Condition conB = lock.newCondition();[/align]
[align=left] con.await(); //生产,,消费[/align]
[align=left] con.signal();生产[/align]
[align=left] set()[/align]
[align=left] {[/align]
[align=left] if(flag)[/align]
[align=left] conA.await(); //生产者,[/align]
[align=left] code......;[/align]
[align=left] flag = true;[/align]
[align=left] conB.signal();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] out()[/align]
[align=left] {[/align]
[align=left] if(!flag)[/align]
[align=left] conB.await(); //消费者[/align]
[align=left] code....;[/align]
[align=left] flag = false;[/align]
[align=left] conA.signal();[/align]
[align=left] }[/align]
wait和sleep的区别:
wait:释放cpu执行权,释放同步中锁。
sleep:释放cpu执行权,不释放同步中锁。
synchronized(锁)
{
wait();
}
停止线程:
stop过时。
原理:run方法结束。run方法中通常定义循环,指定控制住循环线程即可结束。
1,定义结束标记。
2,当线程处于了冻结状态,没有执行标记,程序一样无法结束。
这时可以循环,正常退出冻结状态,或者强制结束冻结状态。
强制结束冻结状态:interrupt();目的是线程强制从冻结状态恢复到运行状态。
但是会发生InterruptedException异常。
线程中一些常见方法:
setDaemon(boolean):将线程标记为后台线程,后台线程和前台线程一样,开启,一样抢执行权运行,
只有在结束时,有区别,当前台线程都运行结束后,后台线程会自动结束。
join():什么意思?等待该线程结束。当A线程执行到了B的.join方法时,A就会处于冻结状态。
A什么时候运行呢?当B运行结束后,A就会具备运行资格,继续运行。
加入线程,可以完成对某个线程的临时加入执行。
notify
public final void notify()
唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个
wait方法,在对象的监视器上等待。
直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。
此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者:
通过执行此对象的同步实例方法。
通过执行在此对象上进行同步的
synchronized语句的正文。
对于
Class类型的对象,可以通过执行该类的同步静态方法。
一次只能有一个线程拥有对象的监视器。
[align=left]class Res[/align]
[align=left]{[/align]
[align=left] private String name ;[/align]
[align=left] private String sex ;[/align]
[align=left] private boolean flag = false;[/align]
public synchronized void set(String
name,String sex)
[align=left] {[/align]
[align=left] if(flag )[/align]
try{this .wait();}catch(Exception
e){}
this.name =
name;
[align=left] [/align]
this.sex =
sex;
[align=left] flag = true ;[/align]
[align=left] this.notify();[/align]
[align=left] }[/align]
[align=left] public synchronized void out()[/align]
[align=left] {[/align]
[align=left] if(!flag )[/align]
try{this .wait();}catch(Exception
e){}
[align=left] System. out.println(name +"........" +sex );[/align]
[align=left] flag = false ;[/align]
[align=left] this.notify();[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]class Input implements Runnable[/align]
[align=left]{[/align]
[align=left] private Res r ;[/align]
[align=left] Input(Res r)[/align]
[align=left] {[/align]
this.r =
r;
[align=left] }[/align]
[align=left] public void run()[/align]
[align=left] {[/align]
int x
= 0;
[align=left] while(true )[/align]
[align=left] {[/align]
[align=left] if(x==0) [/align]
[align=left] r.set( "mike","man" ); [/align]
[align=left] else [/align]
[align=left] r.set( "丽丽","女女女女女" ); [/align]
[align=left] x = (x+1)%2;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]class Output implements Runnable[/align]
[align=left]{[/align]
[align=left] private Res r ;[/align]
[align=left] [/align]
[align=left] Output(Res r)[/align]
[align=left] {[/align]
this.r =
r;
[align=left] }[/align]
[align=left] public void run()[/align]
[align=left] {[/align]
[align=left] while(true )[/align]
[align=left] {[/align]
[align=left] r.out();[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]class InputOutputDemo2[/align]
[align=left]{[/align]
public static void main(String[]
args)
[align=left] {[/align]
[align=left] Res r = new Res();[/align]
[align=left] new Thread(new Input(r)).start();[/align]
[align=left] new Thread(new Output(r)).start();[/align]
[align=left] /*[/align]
[align=left] Input in = new Input(r);[/align]
[align=left] Output out = new Output(r);[/align]
[align=left] Thread t1 = new Thread(in);[/align]
[align=left] Thread t2 = new Thread(out);[/align]
[align=left] t1.start();[/align]
[align=left] t2.start();[/align]
[align=left] */[/align]
[align=left] }[/align]
[align=left]}[/align]
ASP.Net+Android+IO开发、.Net培训、期待与您交流!
相关文章推荐
- 黑马程序员——Java基础---线程的另一个总结(4)--线程通信(互斥),线程范围的共享变量
- 黑马程序员——Java基础---线程间通信
- 黑马程序员——Java基础---线程的另一个总结(3)--互斥,线程锁
- 黑马程序员——Java基础---线程的另一个总结(5)--线程池,线程定时器
- 黑马程序员——Java基础---线程的另一个总结(6)--线程读写锁,缓存小例子
- 黑马程序员——java基础日记——多线程(2)——线程间通信与JDK1.5新特性
- 黑马程序员——Java基础---线程的另一个总结(8)--Semaphere同步工具,控制线程可用线程
- 黑马程序员—11—java基础:有关线程通信的学习笔记和学习心得体会
- 黑马程序员--java基础复习之多线程及线程间通信
- 黑马程序员:Java基础总结----线程池及java5的线程并发库
- 黑马程序员_Java基础_线程间通信,生产者消费者案例,jdk1.5锁机制,守护线程
- 黑马程序员——Java基础---线程的另一个总结(9)--其他同步工具
- 黑马程序员-19-java基础-多线程(2)-死锁与线程间通信(synchronized与Lock的区别及各自用法)
- 黑马程序员——Java语言基础——04.多线程(2)线程间通信
- 黑马程序员——Java基础---线程的另一个总结(7)--condition,await
- Java基础学习总结(88)——线程创建与终止、互斥、通信、本地变量
- Java基础学习总结(88)——线程创建与终止、互斥、通信、本地变量
- 黑马程序员--JAVA基础复习之多线程(三)线程间通信 生产者消费者
- 黑马程序员——Java基础---线程的另一个总结(1)--基本创建方法
- 黑马程序员——JAVA基础---线程之间的通信实现交替输出打印