黑马程序员-多线程(二)
来源:互联网 发布:arttemplate.js api 编辑:程序博客网 时间:2024/05/27 20:11
多线程之间的通信:
其实就是多个线程在操作同一个资源,但是操作的动作不同
用wait(); notify(); notifyAll();操作,如下代码:
class Res<span style="color:#3f7f5f;"> //线程要操作的资源类</span>{private boolean flag=false;private String name;private String sex;public synchronized void setvalue(String name,String sex) {if(flag)try{this.wait();}catch(Exception e){}this.name = name;this.sex=sex;flag=true;this.notify();}public synchronized void show(){if(!flag)try{this.wait();}catch(Exception e){}System.out.println(name+"====="+sex);flag=false;this.notify();}}class Input implements Runnable{Res res;public Input(Res res) {this.res=res;}public void run(){int x=0;while (true) {if(x==0)res.setvalue("张三","男");elseres.setvalue("莉莉","女");x=(x+1)%2;}}}class Output implements Runnable{Res res;public Output(Res res) {this.res=res;}public void run(){while(true){res.show();}}}public class InputOutputDemo1 {public static void main(String[] args) {Res res=new Res();new Thread(new Input(res)).start();new Thread(new Output(res)).start();}}<span style="color:#3f7f5f;">/* wait(); notify(); notifyAll(); 都使用在同步中,因为要持有监视器(锁)的线程操作. 所以要使用在同步中,因为只有同步才有锁. 为什么这些操作线程的方法要定义在Object类中呢? 因为这些方法在操作同步中的线程时,都必须要标识他们所操作线程持有的锁 只有同一个锁上的被等待线程才可以被同一个锁上的notify唤醒. 不可以对不同锁中的线程进行唤醒. 也就是说,等待和唤醒必须是同一个锁 而锁可以是任意对象,所以可以被任意对象调用的方法要定义在Object类中.*/</span>
生产者消费者示例:
生产者消费者示例一:
如下代码:
class Resource{private String name;private int count=0;private boolean flag;public synchronized void setvalue(String name) {while(flag)try{this.wait();}catch(Exception e){}this.name = name+"编号:"+count++;flag=true;System.out.println(Thread.currentThread().getName()+"生产者======"+this.name);this.notifyAll();}public synchronized void show(){while(!flag)try{this.wait();}catch(Exception e){}System.out.println(Thread.currentThread().getName()+"消费者===="+name);flag=false;this.notifyAll();}}class Producer implements Runnable{Resource res=new Resource();public Producer(Resource res) {this.res=res;}public void run(){int x=0;while(true){res.setvalue("产品");x=(x+1)%2;}}}class Consumer implements Runnable{Resource res=new Resource();public Consumer(Resource res) {this.res=res;}public void run() {while(true){res.show();}}}public class ProducerConsumerDemo {public static void main(String[] args) {Resource res=new Resource();new Thread(new Producer(res)).start();new Thread(new Consumer(res)).start();new Thread(new Producer(res)).start();new Thread(new Consumer(res)).start();}}
通过分析发现:
这段代码一直在做着while......notifyAll()的动作,每次都会唤醒所有的线程,造成资源浪费,所以这种方法不推荐使用.下面介绍一直新的方式:JDK1.5的新特性
JDK1.5中提供了多线程升级解决方案,
将同步synchronized替换成了Lock操作
将Object中的wait(),notify(),notifyAll();替换了Condition对象
该对象可以通过lock锁进行获取
该示例中实现了本方只唤醒对方的操作
如下代码:
class Resource1{private String name;private int count=0;private boolean flag;private Lock lock=new ReentrantLock();private Condition condition_pro=lock.newCondition();private Condition condition_con=lock.newCondition();public void setvalue(String name) throws InterruptedException {lock.lock();try {while(flag)condition_pro.await();this.name = name+"编号:"+count++;flag=true;System.out.println(Thread.currentThread().getName()+"生产者======"+this.name);condition_con.signal();} finally {lock.unlock();//一定会释放锁}}public void show() throws InterruptedException{lock.lock();try {while(!flag)condition_con.await();System.out.println(Thread.currentThread().getName()+"消费者===="+name);flag=false;condition_pro.signal();} finally {lock.unlock();//一定会释放锁}}}class Producer1 implements Runnable{Resource1 res;public Producer1(Resource1 res) {this.res=res;}public void run(){int x=0;while(true){try {res.setvalue("产品");} catch (InterruptedException e) {e.printStackTrace();}x=(x+1)%2;}}}class Consumer1 implements Runnable{Resource1 res;public Consumer1(Resource1 res) {this.res=res;}public void run() {while(true){try {res.show();} catch (InterruptedException e) {e.printStackTrace();}}}}public class LockDemo {public static void main(String[] args) {Resource1 res=new Resource1();new Thread(new Producer1(res)).start();new Thread(new Consumer1(res)).start();new Thread(new Producer1(res)).start();new Thread(new Consumer1(res)).start();}}
停止线程:
stop方法已经过时
那么该如何停止线程呢?
只有一种,run方法结束
开启多线程运行,运行的代码通常都是循环结构的,所以只要控制住循环就能让run方法结束,也就是线程结束
如下代码:
class StopThread implements Runnable{private boolean flag=true;public void run() {while(flag){System.out.println("Thread Run!");}}public void setFlag(){flag=false;}}public class StopThreadDemo1 {public static void main(String[] args) {StopThread st=new StopThread();Thread t1=new Thread(st);Thread t2=new Thread(st);t1.start();t2.start();int x=0;while (true) {if(x++ ==100){st.setFlag();break;}System.out.println("main...........");}System.out.println("over");}}
通过标记来完成对run方法中的循环进行控制,当主函数中的循环跑了100次后设置线程的flag标记为false;
以下还有一种特殊情况是没办法结束的:
当线程处于wait()冻结状态
就不会读取到flag标记,就无法结束循环
代码如下:
class StopThread implements Runnable{private boolean flag=true;public synchronized void run() {while(flag){try {this.wait();} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName()+":异常了....");}System.out.println(Thread.currentThread().getName()+":Run!");}}public void setFlag(){flag=false;}}public class StopThreadDemo1 {public static void main(String[] args) {StopThread st=new StopThread();Thread t1=new Thread(st);Thread t2=new Thread(st);t1.start();t2.start();int x=0;while (true) {if(x++ ==100){st.setFlag();break;}System.out.println("main..........."+x);}System.out.println("over");}}
当没有指定的方式让冻结的线程恢复到运行状态时,这时需要清除线程的冻结状态
强制让线程回复到运行状态中来,这样就可以操作标记让线程结束
Thread类中提供了该方法 interrupt();
代码如下:
class StopThread implements Runnable{private boolean flag=true;public synchronized void run() {while(flag){try {this.wait();} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName()+":异常了....");flag=false;}System.out.println(Thread.currentThread().getName()+":Run!");}System.out.println(Thread.currentThread().getName()+":over!");}public void setFlag(){flag=false;}}public class StopThreadDemo1 {public static void main(String[] args) {StopThread st=new StopThread();Thread t1=new Thread(st);Thread t2=new Thread(st);t1.start();t2.start();int x=0;while (true) {if(x++ ==100){st.setFlag();t1.interrupt();t2.interrupt();break;}System.out.println("main..........."+x);}System.out.println("over");}}
守护线程:
setDaemon(boolean on)
也称为后台线程,如果当前台线程都结束后,后台线程自动结束,jvm退出.
守护线程必须在线程启动之前调用,也就是说要在线程启动之前设置是否是守护线程
比如 圣斗士-星矢中的圣斗士就是围着雅典娜转,雅典娜一挂圣斗士也就没啥事了,就没有存在的意义了
如下代码:
代码中主函数代码结束后守护线程也自动结束
class Thread1 implements Runnable{public void run(){while(true){System.out.println("Thread1");}}}class Thread2 implements Runnable{public void run(){while(true){System.out.println("Thread2");}}}public class GuardianDemo {public static void main(String[] args) {Thread1 t1=new Thread1();Thread2 t2=new Thread2();Thread t3=new Thread(t1);Thread t4=new Thread(t2);t3.setDaemon(true);t4.setDaemon(true);t3.start();t4.start();for(int x=0;x<=100;x++){System.out.println("main........");}}}
当主函数中的for循环完成后,所有线程都结束了,jvm退出,原本在Thread1和Thread2中的都是无限循环的,设置了守护线程后当主函数执行完成后自动退出....
Join:
等待线程结束,等待join的那个线程结束主线程才会继续,也就是说,如果A线程碰到了B线程的join,那么A线程会等待,等待到B线程执行完毕才会继续执行,如下代码:
class Join implements Runnable{public void run(){for(int x=0;x<100;x++){System.out.println("Join......."+x);}}}class Join1 implements Runnable{public void run(){for(int x=0;x<100;x++){System.out.println("Join1......."+x);}}}public class JoinDemo {public static void main(String[] args) throws InterruptedException {Join j1=new Join();Join1 j2=new Join1();Thread t1 =new Thread(j1);Thread t2 =new Thread(j2);t1.start();t1.join();t2.start();//t1.join();for(int x=0;x<100;x++){System.out.println("JoinDemo......."+x);}}}
通过上面的代码发现只有在t1线程执行完毕后t2和主线程交替执行,如果t1.join放在t2.start()后面的话,t1和t2线程会交替执行,直到t1执行完毕后主线程才会执行,如果这时t2线程还没有结束的话,主线程会和t2交替执行.
优先级&线程名称&线程组:
toString:覆盖了Object类中的toString方法,可以打印出线程名称和优先级及线程组
线程组:谁开启的线程就属于哪个组
优先级:优先级高的线程抢CPU的频率会高一点,所有线程的默认优先级是5
优先级可以通过setPriority来改变,跨度最大的三个优先级如 1 5 10,这三个优先级有专用的常量值,MAX_PRIORITY:10 MIN_PRIORITY:1 NORM_PRIORITY:5
yield:暂停当前正在执行的线程对象,并执行其他线程。能够稍微减缓线程的执行,让其他的线程更能有机会抢到CPU的执行权
- 黑马程序员--多线程(二)
- 黑马程序员-多线程(二)
- 黑马程序员_JAVA多线程(二)
- 黑马程序员 多线程(二)
- 黑马程序员_多线程二
- 黑马程序员 多线程(二)。
- 黑马程序员_多线程(二)
- 黑马程序员-------多线程(二)
- 黑马程序员---多线程(二)
- 黑马程序员——多线程(二)
- 黑马程序员学习日记----多线程(二)
- 黑马程序员--.Net多线程总结(二)
- 黑马程序员java笔记之二-----多线程
- 黑马程序员 java多线程笔记(二)
- 黑马程序员——多线程(二)
- 【黑马程序员】多线程(二) 第十二天
- 黑马程序员——多线程(二)
- 黑马程序员——多线程(二)
- Codeforces Round #277.5 解题报告
- 串口通信编程--多线程异步方式
- Hadoop-2.2.0中文文档—— Shell命令
- XML(三)
- 位运算符的介绍
- 黑马程序员-多线程(二)
- 项目-v0.0.2
- 你还在用jquery.lazyload这个坑爹的图片分屏加载插件么?
- jQuery页面滚动图片等元素动态加载实现
- LeetCode(116) Populating Next Right Pointers in Each Node
- 多个控制器
- 感觉cocos的定时器不好用, 自已封装了一个
- java如何判断一个文件的类型
- 深入研究Clang(四) Clang编译器的简单分析