黑马程序员技术交流社区
标题: 黑马程序员-JAVA-面向对象-第十二天 [打印本页]
作者: 支离疏者 时间: 2015-5-20 20:14
标题: 黑马程序员-JAVA-面向对象-第十二天
主题:多线程1线程间通讯
其实是多个线程在操作同一个资源,但是操作的动作不同
1.是不是两个或两个以上的线程。解决办法 两个线程都要被同步
2.是不是同一个锁。 解决办法 找同一个对象作为锁。
2等待唤醒机制
wait()后,线程就会存在线程池中,notify()后就会将线程池中的线程唤醒
notifyAll():唤醒线程池中所有的线程
例一:
- /对InputOutput的优化,双线程输出Mikeman和韩梅梅女
- class Rec
- {
- private String name;//优化1.私有化
- private String sex;
- private boolean flag=false;
- public synchronized void set(String name,String sex)//优化2构建对外访问,同步函数
- {
- if (this.flag)//如果真运行wait(),一开始为false,不运行,运行一次后变为true,
- try{this.wait();}catch(Exception e){}//wait()和后面的notify()必须是同步锁的r,标识锁
- this.name=name;
- this.sex=sex;
- this.flag=true;
- this.notify();
- }
- public synchronized void out()//优化2构建对外访问,同步函数
- {
- if (!this.flag)//如果真运行wait(),一开始flag为true,所以是!flag,第一次不运行,运行一次后flag变为false
- try{this.wait();}catch(Exception e){}
- System.out.println(name+sex);
- this.flag=false;
- this.notify();
- }
- }
- class Input implements Runnable
- {
- private Rec r;
- Input(Rec 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 Rec r;
- Output(Rec r)
- {
- this.r=r;
- }
- public void run()
- {
- while(true)
- {
- r.out();
- }
- }
- }
- class InputOutput
- {
- public static void main(String[] args)
- {
- Rec r =new Rec();
- new Thread(new Input(r)).start();//优化三,匿名函数,简化书写
- new Thread(new Output(r)).start();
- }
- }
复制代码
wait(),notify(),notifyAll()
都使用在同步中,因为要对持有监视器(锁)的线程操作
所以要使用在同步中,因为只有同步才具有锁
为什么这些操作线程的方法要定义在Object类中?
因为这些方法在操作同步线程中线程时,都必须要标识它们所操作线程只有的锁
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒
不可以对不同的锁中的线程进行唤醒
也就是说,等待和唤醒必须是同一个锁
而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中
例二:while (this.flag)//让唤醒的线程都重新判断标记
- while (this.flag)//让唤醒的线程都重新判断标记
- {
- try
- {this.wait();}
- catch (Exception e){}
- }
- this.name=name+"--"+count++;
- System.out.println(Thread.currentThread().getName()+"--"+"生产者"+"--"+this.name);
- flag=true;
- this.notifyAll();//唤醒对方线程,避免死锁
复制代码
3 JDK1.5版升级版
JDK1.5中提供了多线程升级解决方案,显示的锁机制,和显示锁对象等待唤醒操作机制
将同步synchronized替换成了Lock操作
将Object中的wait,notify,notifyAll,替换成了Condition对象
该对象可以Lock锁 进行获取。一个锁可以对应多个condition对象
Lock:替代了Synchronized
lock
unlock
newCondition()
Condition:替代了Object wait notify notifyAll
await();
signal();
signalAll();
注意:释放锁的动作一定要执行(finally{})
例三:
- class Res{
- private String name;
- private int count=1;
- private boolean flag =false;//资源空间的标记
- private Lock lock=new ReentrantLock()
- private Condition condition_pro=lock.newCondition();
- private Condition condition_con=lock.newCondition();//一个锁可以对应多个Condition对象
- public void set(String name){
- lock.lock();//代替synchronized
- try{
- while (this.flag)
- condition_pro.await();//代替wait()
- this.name=name+"--"+count++;
- System.out.println(Thread.currentThread().getName()+"--"+"生产者"+"--"+this.name);
- flag=true;
- condition_con.signal();//代替notifyAll()
- }
- finally {
- lock.unlock();
- }
- }
- public void get(){
- lock.lock();
- try{
- while(!flag)
- condition_con.await();
- System.out.println(Thread.currentThread().getName()+"--"+"消费者"+"------"+this.name);
- flag=false;
- condition_pro.signal();
- }
-
- finally {
- lock.unlock();
- }
-
- }
- }
复制代码
4 停止线程
run方法结束,就会停止线程。开启多线程运行,运行代码通常是循环结构,只要控制住循环就可以让线程结束。方法:改变标记使循环结束
特殊情况:
当线程处于了冻结状态,就不会取到标记,那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态时,这是需要对冻结进行清除。强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
Thread类中提供了该方法 线程.interrupt(); 中断异常(此时会发生异常)
5 守护线程、join方法、优先级
守护线程:(后台线程)
setDaemon将线程标记为守护线程或者用户线程。
setDaemon在启动线程前调用。当现存线程都是守护线程后,jvm退出
例:t1.setDaemon(true);
Join方法
join():抢夺cpu执行权
当A线程执行到了B线程join方法时,A就会等待,等B线程执行完,A才会执行。Join可以用来临时加入线程执行。
例:t1.join();
优先级:
setPriority(1-10)设置优先级
有三个标准:Thread.MAX_PRIORITY(10)
Thread.MIN_PRIORITY(1)
Thread.NORM_PRIORITY(5)
优先级越高,抢夺cpu执行权的几率越高
例:t1.setPriority(Thread.MAX_PRIORITY);
yield:暂停当前正在执行的线程对象,并执行其他线程
例:Thread.yield();
作者: Im海洋 时间: 2015-5-20 21:32
看得懂的直接跳过,看不懂的还是看不懂
作者: 13699266500 时间: 2015-5-20 21:48
继续努力!!
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |