黑马程序员--Java基础之多线程(2)
2013-11-25 15:11
162 查看
------------------
android培训、java培训、期待与您交流! ---------------------
四、线程间通信---等待唤醒机制
1、线程间通信:就是多个线程在操作同一个资源,但是操作的动作不同。
如生产者和消费者的例子,比如轮流对人对象姓名年龄的输入和输出动作。
2、线程间的通信其实就是---不同动作间的同步问题!
操作同一资源的代码分别在不同的地方,要将他们同步在一起,并且还要轮流操作。
比如对人对象进行姓名年龄的输入和输出动作,输入动作和输出动作分别在不同的线程中,
而且这两个操作必须同步,还要轮流进行操作。
3、解决办法:使用同步Synchronized,用同一个锁使不同动作同步(可以使用要操作的同一个对象作为锁)。
使用flag标记位,通过判断标记位决定是否可以操作,结合wait方法等待,notify方法唤醒单个线程,
notifyAll方法唤醒所有等待的线程,实现不同动作的轮流操作。
wait(),notify(),notifyAll()方法必须使用在同步中,且必须拥有同步的锁。
4、示例代码:(轮流对人对象姓名年龄的输入和输出动作)
5、notify方法会造成死锁,
这是因为,等待的线程都按顺序存放在线程池中,notify通常唤醒线程池中的第一个线程,
也就是第一个wait的线程,这回造成死锁。notifyAll()方法用来解决死锁问题。但是对方线程会抢占资源。
6、JDK1.5改进:Lock:lock,unlock。 Condition,await,signal。显式的锁机制,以及显式的锁上的等待唤醒机制。
JDK1.5中提供了多线程升级解决方案,将同步Synchronized替换成现实Lock操作。
将Object中的wait,notify,notifyAll 替换成了condition对象。可以通过Lock的锁,获取condition对象。
下面是多个生产者和消费者的代码示例:
五、停止线程、守护线程、线程优先级以及join方法yield方法
1、停止线程
stop()方法已经过时,一般代码运行完毕,该线程就结束了。
特殊情况:循环状态下,当线程处于冻结状态,就不会读取标记,也就不能结束线程。这时可以使用Thread类提供的方法 interrupt();对冻结清楚,然后修改标记,使循环结束。
2、守护线程
setDaemon (true)将该线程设置为守护线程。
守护线程又称后台线程,后台线程依赖于前台线程,前台线程只要一结束,后台线程也就随之结束。
注意:该方法必须在启动线程前调用。当正在运行的线程都是守护线程时,Java虚拟机退出,程序结束。
3、线程优先级
线程优先级共有是个级别:1-10 。
一般分为三个层次:MAX_PRIORITY(10);MIN_PRIORITY(1);NORM_PRIORITY(5)。
可以通过setPriority(int newPriority);来改变线程的优先级状态。
4、join方法,yield方法。
join(),等待该线程终止。当A线程执行到了B线程的join方法时,A就会等待,等B线程都执行完,A才会执行。
Join()可以用来临时加入线程执行。
yield(),暂停当前正在执行的线程对象,并执行其他线程。临时释放执行权,有利于线程的平均运行。
android培训、java培训、期待与您交流! ---------------------
四、线程间通信---等待唤醒机制
1、线程间通信:就是多个线程在操作同一个资源,但是操作的动作不同。
如生产者和消费者的例子,比如轮流对人对象姓名年龄的输入和输出动作。
2、线程间的通信其实就是---不同动作间的同步问题!
操作同一资源的代码分别在不同的地方,要将他们同步在一起,并且还要轮流操作。
比如对人对象进行姓名年龄的输入和输出动作,输入动作和输出动作分别在不同的线程中,
而且这两个操作必须同步,还要轮流进行操作。
3、解决办法:使用同步Synchronized,用同一个锁使不同动作同步(可以使用要操作的同一个对象作为锁)。
使用flag标记位,通过判断标记位决定是否可以操作,结合wait方法等待,notify方法唤醒单个线程,
notifyAll方法唤醒所有等待的线程,实现不同动作的轮流操作。
wait(),notify(),notifyAll()方法必须使用在同步中,且必须拥有同步的锁。
4、示例代码:(轮流对人对象姓名年龄的输入和输出动作)
public class ThreadCommunication { public static void main(String[] args) { Person p = new Person(); Input in = new Input(p);//两个线程操作同一个对象,可以将该对象作为参数传入。 //也可以使用单例设计模式,但是太麻烦 Output out = new Output(p); Thread t1 = new Thread(in); Thread t2 = new Thread(out); t1.start(); t2.start(); } } class Person{ private String name; private String sex; private boolean flag = false; //设置姓名和性别的方法set public synchronized void set(String name,String sex){ while(flag){//如果flag为true说明已经设置好姓名和性别,设置操作需要等待一下。 //如果flag为false说明设置的东西已经被取走,可以进行设置操作了,则继续往下走。 //这里使用while方法,不适用if方法,这是因为while循环使线程被唤醒时依然会判断一下标记! try {this.wait();} catch (InterruptedException e){}//同步函数的锁是this } this.name = name; this.sex = sex; flag = true;//设置完毕,将标志位设置为true,表示已经设置完毕 this.notifyAll();//设置完毕唤醒其他线程 //this.notify();//notify()方法会造成死锁,因为它通常会唤醒线程池中第一个wait的方法。 } //打印姓名和性别的方法get public synchronized void get(){ while(!flag){ try {this.wait();} catch (InterruptedException e) {} } System.out.println(this.name+"-------------"+this.sex); flag = false; this.notifyAll(); } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } } class Input implements Runnable{ private Person p; private int x = 1; Input(Person p){ this.p = p; } @Override public void run() { while(true){ if(x==1){ p.set("丽丽","女"); x++; } else{ p.set("John","man"); x--; } } } } class Output implements Runnable{ private Person p; Output(Person p){ this.p = p; } @Override public void run() { while(true){ p.get(); } } }
5、notify方法会造成死锁,
这是因为,等待的线程都按顺序存放在线程池中,notify通常唤醒线程池中的第一个线程,
也就是第一个wait的线程,这回造成死锁。notifyAll()方法用来解决死锁问题。但是对方线程会抢占资源。
6、JDK1.5改进:Lock:lock,unlock。 Condition,await,signal。显式的锁机制,以及显式的锁上的等待唤醒机制。
JDK1.5中提供了多线程升级解决方案,将同步Synchronized替换成现实Lock操作。
将Object中的wait,notify,notifyAll 替换成了condition对象。可以通过Lock的锁,获取condition对象。
下面是多个生产者和消费者的代码示例:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ProAndCon { public static void main(String[] args){ Resource res = new Resource(); Producer pro = new Producer(res); Consumer con = new Consumer(res); Thread t1 = new Thread(pro);//制造多个生产者和消费者 Thread t2 = new Thread(pro); Thread t3 = new Thread(pro); Thread t4 = new Thread(con); Thread t5 = new Thread(con); Thread t6 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start(); } } class Resource{ private int num; private boolean flag = false; private Lock lock = new ReentrantLock();//定义一个锁,它的锁和解锁操作代替了同步操作 private Condition pro_condition = lock.newCondition();//生产者的 private Condition con_condition = lock.newCondition();//消费者的 public void set(){ lock.lock();//首先上锁 try { while(flag){ pro_condition.await();//如果有产品,生产者wait } ++num; System.out.println(Thread.currentThread().getName()+"生产的第"+num+"个产品"); flag = true;//生产后设置标记位为true con_condition.signalAll();//唤醒所有消费者 } catch (InterruptedException e) { }finally{ lock.unlock();//最后别忘了解锁,解锁放在finally语句中,确保一定会执行解锁 } } public void get(){ try { lock.lock(); while(!flag){ con_condition.await(); } System.out.println(Thread.currentThread().getName()+"消费了第+++++++++++"+num+"个产品+++++++++++"); flag = false; pro_condition.signalAll();//唤醒所有生产者 } catch (InterruptedException e) { }finally{ lock.unlock(); } } } class Producer implements Runnable{ private Resource res ; Producer(Resource res){ this.res = res; } @Override public void run() { while(true){ res.set(); } } } class Consumer implements Runnable{ private Resource res; Consumer(Resource res){ this.res = res; } @Override public void run() { while(true){ res.get(); } } }
五、停止线程、守护线程、线程优先级以及join方法yield方法
1、停止线程
stop()方法已经过时,一般代码运行完毕,该线程就结束了。
特殊情况:循环状态下,当线程处于冻结状态,就不会读取标记,也就不能结束线程。这时可以使用Thread类提供的方法 interrupt();对冻结清楚,然后修改标记,使循环结束。
2、守护线程
setDaemon (true)将该线程设置为守护线程。
守护线程又称后台线程,后台线程依赖于前台线程,前台线程只要一结束,后台线程也就随之结束。
注意:该方法必须在启动线程前调用。当正在运行的线程都是守护线程时,Java虚拟机退出,程序结束。
3、线程优先级
线程优先级共有是个级别:1-10 。
一般分为三个层次:MAX_PRIORITY(10);MIN_PRIORITY(1);NORM_PRIORITY(5)。
可以通过setPriority(int newPriority);来改变线程的优先级状态。
4、join方法,yield方法。
join(),等待该线程终止。当A线程执行到了B线程的join方法时,A就会等待,等B线程都执行完,A才会执行。
Join()可以用来临时加入线程执行。
yield(),暂停当前正在执行的线程对象,并执行其他线程。临时释放执行权,有利于线程的平均运行。
相关文章推荐
- 黑马程序员_java基础多线程
- 黑马程序员-JAVA基础-多线程概念与创建
- 黑马程序员——Java基础—多线程
- 黑马程序员_Java基础(4)--多线程
- 黑马程序员JAVA基础-多线程
- 黑马程序员————java基础(多线程)
- 黑马程序员——Java基础---理解多线程
- 黑马程序员——JAVA基础----多线程(一)
- 黑马程序员-JAVA基础之多线程
- 黑马程序员——Java基础---多线程
- 黑马程序员--java基础--多线程
- 黑马程序员——java基础之多线程
- 黑马程序员 Java基础 --->多线程
- <黑马程序员>---java基础---多线程知识
- 黑马程序员_Java基础:实现多线程对共有数据的同步操作
- 黑马程序员——JAVA基础之多线程的线程间通讯等
- 黑马程序员---java基础知识之多线程
- 黑马程序员——Java基础->多线程
- 黑马程序员_Java多线程基础
- 黑马程序员_java基础--多线程