多线程__下
来源:互联网 发布:网络主播文儿的歌曲 编辑:程序博客网 时间:2024/03/29 07:47
线程间通讯:
wait和sleep的区别:其实就是多个线程在操作同一个资源,操作的动作不同
wait:释放cpu执行权,释放同步中的锁。sleep:释放cpu执行权,不释放同步中的锁。
/**线程间通信示例需求:输入一次信息,打印一次信息分析:需要两个线程一个是输入线程一个是打印线程有一个共享资源:用来存储信息和获取信息思路:定义三个类类Rec:共享的资源类Input:具备输入信息的功能类Output:具备打印信息的功能*/class Rec//定义一个对象{String name;String sex;boolean flag = false; //定义一个标记,用于控制线程输入一次,打印一次}class Input implements Runnable//具备输入功能的对象{private Rec r;Input(Rec r)//传入要操作的对象{this.r = r;}public void run()//输入方法{int x = 0;while (true){while (r.flag){try{r.wait();}catch(Exception e){}}synchronized(r){if (x == 0){r.name = "张三";//输入信息r.sex = "++++++男";}else{r.name = "李四";r.sex = "女";}x = (x+1)%2;//此代码的结果不是0就是1,利用这个特性来控制信息的交替输入,使用boolean数据类型也可以实现r.flag = true;//该语句的结果控制信息输入一次后,就进入冻结状态r.notify();//唤醒线程池中冻结的线程}}}}class Output implements Runnable{private Rec r;Output(Rec r){this.r = r;}public void run(){while (true){synchronized(r){while (!r.flag)//要让线程交替执行,就必须使其满足的条件互斥,所以这里条件是!r.flag{try{r.wait();}catch(Exception e){}}System.out.println(r.name+"++++++"+r.sex);r.flag = false;//执行完毕后修改值,让该线程执行wait()进入冻结状态,并跳转到输入功能r.notify();}}}}class InputOutputDemo{public static void main(String[] args) {Rec r = new Rec();//建立共享资源对象Input in = new Input(r);//将共享资源传入具备输入功能的对象中Output ou = new Output(r);//将共享资源传入具备输出功能的对象中Thread t1 = new Thread(in);//建立线程Thread t2 = new Thread(ou);t1.start();//开启线程t2.start();}}
wait():
notify();
notifyAll();
都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义Object类中呢?
notify();
notifyAll();
都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作的线程的锁,只有同一个锁上的等待线程,可以被同一个锁(notify())唤醒。不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒的线程必须持有相同的锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。
生产消费者案例:
/**需求:多条线程生产商品,多条线程销售商品,且保证生产一个销售一个分析:定义多条线程生产商品定义多条线程销售商品定义一个生产者类,该类具备生产商品的功能定义一个消费者,该类具备销售商品的功能该程序中的共享资源是商品,商品可以被生产和销售*/class Res{private String name;private int count = 1;private boolean flag = false;public synchronized void set(String name)//将生产功能封装起来{/*上一个案例中,是一个线程负责输入,一个线程负责输出这个案例是,多个线程负责输入,多个线程负责输出这里的while不可以使用if代替,否则会出现,生产两个商品只卖出了一个商品,或者是生产一个商品却卖出了两次那是因为,当线程冻结后,被唤醒的线程直接执行wait后的语句,而不用判断flag标记而造成的此处改为while语句就可以避免这样的情况发生,被唤醒的线程将会再次判断flash标记这是本演示案例的重点之一*/while (flag){try{wait();}catch(Exception e){}}this.name = name+"----"+count++;//这句代码不能放在while语句前面,否则会出现先消费后生产的怪异现象System.out.println(Thread.currentThread().getName()+"-------生产者-----------"+this.name);flag = true;/*本案例重点二该出使用notifyAll是为了唤醒除本方线程的其他线程如果使用notify,将有可能一直唤醒本方线程,而本方线程的flag一直是false,下面的语句得不到执行,将会出现线程停止不动的现象*/notifyAll();}public synchronized void out(){while (!flag){try{this.wait();}catch(Exception e){}}System.out.println(Thread.currentThread().getName()+"--消费者--"+this.name);flag = false;notifyAll();}}class Producer implements Runnable{private Res r;Producer(Res r){this.r = r;}public void run(){while (true){r.set("商品");//直接调用set方法}}}class Customer implements Runnable{private Res r;Customer(Res r){this.r = r;}public void run(){while (true){r.out();}}}class ProducerCustomerDemo {public static void main(String[] args) {Res r = new Res();Producer pro = new Producer(r);Customer cus = new Customer(r);Thread t1 = new Thread(pro);//开启两个生产者线程Thread t2 = new Thread(pro);Thread t3 = new Thread(cus);//开启两个消费者线程Thread t4 = new Thread(cus);t1.start();t2.start();t3.start();t4.start();}}
可不可以只唤醒对方呢?有的。
JAVA1.5版本之后出现了一个新的包java.util.concurrent.locks
该包中提供了condition接口和lock接口
将同步Synchronized替换成现实Lock操作。
将Object中的wait,notify notifyAll,替换成了Condition对象。
该对象可以对Lock锁 进行获取。
该示例中,实现了本方只唤醒对方操作。
Lock:替代了Synchronized
lock
unlock
newCondition()
Condition:替代了Object中的 wait notify notifyAll
await();
signal();
signalAll();
将Object中的wait,notify notifyAll,替换成了Condition对象。
该对象可以对Lock锁 进行获取。
该示例中,实现了本方只唤醒对方操作。
Lock:替代了Synchronized
lock
unlock
newCondition()
Condition:替代了Object中的 wait notify notifyAll
await();
signal();
signalAll();
生产消费者案例代码升级:
/**使用1.5版本出现的lock和condition对程序进行升级优化*/import java.util.concurrent.locks.*;class Res{private String name;private int count = 1;private boolean flag = false;private Lock lock = new ReentrantLock();//定义一个锁private Condition con_pro = lock.newCondition(); //创建一个生产者conditionprivate Condition con_cus = lock.newCondition();//创建一个消费者conditionpublic void set(String name) throws InterruptedException{lock.lock();//获取锁,也可称为加锁try{while (flag){con_pro.await()//冻结pro中线程}this.name = name+"----"+count++;System.out.println(Thread.currentThread().getName()+"-------生产者-----------"+this.name);flag = true;con_cus.signal();//唤醒消费者的线程}finally{lock.unlock;//释放锁,一定要执行}}public void out() throws InterruptedException{lock.lock();//加锁try{while (!flag){con_cus.await();//冻结本方的线程}System.out.println(Thread.currentThread().getName()+"--消费者--"+this.name);flag = false;con_pro.signal();//唤醒对方线程}finally{lock.unlock();//释放锁}}}class Producer implements Runnable{private Res r;Producer(Res r){this.r = r;}public void run(){while (true){r.set("商品");//直接调用set方法}}}class Customer implements Runnable{private Res r;Customer(Res r){this.r = r;}public void run(){while (true){r.out();}}}class ProducerCustomerDemo {public static void main(String[] args) {Res r = new Res();Producer pro = new Producer(r);Customer cus = new Customer(r);Thread t1 = new Thread(pro);//开启两个生产者线程Thread t2 = new Thread(pro);Thread t3 = new Thread(cus);//开启两个消费者线程Thread t4 = new Thread(cus);t1.start();t2.start();t3.start();t4.start();}}
控制线程(停止线程,加入线程,暂停线程,控制线程的优先级)
特殊情况:只有一种,run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。
当线程处于了冻结状态。就不会读取到标记。那么线程就不会结束。
处理方法:
当没有指定的方式让冻结的线程恢复到运行状态时,如果需要对冻结状态进行清除,
强制让线程恢复到运行状态中来。这时 可以使用Thread类中的interrupt()方法来清除冻结,
当没有指定的方式让冻结的线程恢复到运行状态时,如果需要对冻结状态进行清除,
强制让线程恢复到运行状态中来。这时 可以使用Thread类中的interrupt()方法来清除冻结,
这样就可以继续判断操作标记让线程结束。
代码示例:
class StopThread implements Runnable{private boolean flag =true;public synchronized void run(){while(flag){try{wait();}catch (InterruptedException e)//处理异常{System.out.println(Thread.currentThread().getName()+"....Excepiton");flag = false;//改变标记,让进入运行状态的线程开始执行}System.out.println(Thread.currentThread().getName()+"....run");}}public void changeFlag(){flag = false;//控制循环的标记}}class StopThreadDemo{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 num = 0;while(true){if(num++ == 60){t1.interrupt();//强制将冻结状态的线程终止,并让其进入运行状态t2.interrupt();//调用此方法会出现InterruptException异常break;}System.out.println(Thread.currentThread().getName()+"......."+num);}System.out.println("over");}}
守护线程(后台线程)
守护线程的特点:当前台线程执行完毕,只剩下守护线程时,守护线程自动结束
join:
当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
join可以用来临时加入线程执行。
join:
当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
join可以用来临时加入线程执行。
理解:调用了join()方法的线程,抢夺了CPU的执行权,这时,其他线程将会被冻结,该线程join结束,其他线程恢复到运行状态
应用:多个线程运行时,临时加入一个线程,并让其执行完。
优先级(Priority)
优先级的三种级别
MAX_PRIORITY
MIN_PRIORITY
NORM_PRIORITY(主线程的默认级别)
改变优先级的方法:Thread.setPriority(MAX_PRIORITY)
优先级的大小,可以控制线程获取执行权的概率;优先级越大,获取执行权的概率越大,优先级越小,获取执行权的概率越小。
yield()
暂停(释放执行权)当前正在执行的线程对象,并执行其他线程。
线程中使用到的方法
void interrupt()
中断线程。
中断线程。
java.util.concurrent
|--lock
|--lock():获取锁
|--unlock():释放锁
|--condition
|--await():等待
|--signal():唤醒一个等待线程
|--signalAll():唤醒所有等待线程
0 0
- 多线程__下
- 黑马程序员——Java基础__多线程(下)
- 黑马程序员__多线程
- 黑马程序员__多线程
- 黑马程序员__多线程
- java基础__多线程
- 多线程__上
- 黑马程序员__多线程
- 黑马程序员__多线程
- 黑马程序员__多线程
- 多线程__下载
- 黑马程序员__多线程1
- 黑马程序员__多线程2
- 多线程13__线程基本概念
- String类__ 下
- 黑马程序员__Java基础__多线程
- 黑马程序员__JAVA基础__多线程
- 黑马程序员Java基础__多线程
- C#中如何获取字体类型,颜色,和大小.
- 异常:System.IO.FileNotFoundException: 未能加载文件或程序集“Microsoft.mshtml
- ios申请真机调试( xcode 5)详细解析
- 2014 第十一届浙江省程序设计竞赛
- Cocos2x 适配
- 多线程__下
- java枚举一个目录下的所有文件的问题
- POJ1006
- 安卓 再按一次退出
- 数据库死锁
- HDU - 3465 Life is a Line
- PDO 与 MYSQL Replace 的细节
- Unity3D 错误,nativeVideoFrameCallback解决方法。
- 简单JNI实例