黑马程序员_多线程2
来源:互联网 发布:性价比高的汽车知乎 编辑:程序博客网 时间:2024/05/19 20:37
------- android培训、java培训、期待与您交流! ----------
一、线程间通讯
所谓线程间通讯,其实就是多个线程在操作同一资源,但操作的动作不同。
在Java1.5版本之前,实现线程间通讯的解决方案是:等待唤醒机制。
该机制用到了Object类中的3个方法:wait()、notify()、notifyAll()。
这3个方法都使用在同步中,因为要对持有对象监视器(锁)的线程操作,只有同步才具有锁。
之所以定义在Object类中,是因为这些方法在操作同步中线程时,都必须标识它们所操作线程持有的锁,只有同一个锁上的被等待进程,可以被同一个锁上notify唤醒,不可以唤醒不同锁中的线程。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
例如在下面“生产者和消费者”这个例子中,有2个生产者和2个消费者总共4个线程,每次操作共享数据时都用while(flag)判断资源标记来决定是否需要wait(),在操作完共享数据后使用notifyAll()唤醒所有生产者线程和消费者线程。
class Resource {private String name;private int count = 1;private boolean flag = false;public synchronized void set(String name) {while(flag) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.name = name + count ++;System.out.println(Thread.currentThread().getName() + "...生产.." + this.name);flag = true;this.notifyAll();}public synchronized void out() {while(!flag) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + "...消费...." + name );flag = false;this.notifyAll();}}
在Java1.5版本之后,Java提供了一种新的线程间通讯的解决方案:Lock 和 Condition
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
这个解决方案意味着可以唤醒特定的线程,比唤醒所有线程效率更高。
用这个方法改进后的完整程序代码如下:
import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;class Resource {private String name;private int count = 1;private boolean flag = false;private final Lock lock = new ReentrantLock();private final Condition condition_pro = lock.newCondition();private final Condition condition_con = lock.newCondition();public void set(String name) throws InterruptedException {lock.lock();try {while(flag) {condition_pro.await();}this.name = name + count ++;System.out.println(Thread.currentThread().getName() + "...生产.." + this.name);flag = true;condition_con.signal();}finally {lock.unlock();}}public synchronized void out() 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 Producer implements Runnable {private Resource r;Producer(Resource r) {this.r = r;}public void run() {for(int x = 0; x < 100; x++) {try {r.set("cola");} catch (InterruptedException e) {e.printStackTrace();}}}}class Consumer implements Runnable {private Resource r;Consumer(Resource r) {this.r = r;}public void run() {for(int x = 0; x < 100; x++) {try {r.out();} catch (InterruptedException e) {e.printStackTrace();}}}}public class ProducerConsumer {public static void main(String[] args) {Resource r = new Resource();new Thread(new Producer(r)).start();new Thread(new Producer(r)).start();new Thread(new Consumer(r)).start();new Thread(new Consumer(r)).start();}}
二、停止线程
注:stop方法已过时不再使用。
1.定义循环结束标记
因为线程运行代码一般都是循环,只要控制了循环即可。
class StopDemo implements Runnable {private boolean flag = true;public void run() {while(flag) {System.out.println(Thread.currentThread().getName()+"...run");}}public void changeFlag() {flag = false;}}
但这个方法有一种特殊情况会无法停止线程:当线程处于冻结状态,就不会读取到flag标记,线程就不会结束。
于是有了下面的第2种方法。
2.使用interrupt(中断)方法
该方法是结束线程的冻结方法,使线程回到运行状态中来。
这样就可以操作flag标记让线程结束。
class StopDemo implements Runnable {private boolean flag = true;public synchronized void run() {while(flag) {try {wait();} catch (InterruptedException e) {flag = false;}System.out.println(Thread.currentThread().getName()+"...run");}}}
三、守护线程
public final void setDaemon(boolean on)
将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
该方法必须在启动线程前调用。
参数on
- 如果为 true
,则将该线程标记为守护线程。
四、优先级
public final void setPriority(int newPriority)
更改线程的优先级。
参数:newPriority
- 要为线程设定的优先级(1~10)。
static int MAX_PRIORITY
线程可以具有的最高优先级(10)。
static int MIN_PRIORITY
线程可以具有的最低优先级(1)。
static int NORM_PRIORITY
分配给线程的默认优先级(5)。
五、join和yield
public final void join() throws InterruptedException
等待该线程终止。
该方法可以指定某一个线程加入,当该线程执行完毕再继续执行原线程。
public static void yield()
暂停当前正在执行的线程对象,并执行其他线程。
该方法可以稍微减缓线程运行,达到各线程都有机会平均运行的效果。
六、用匿名内部类写多线程
//第一种new Thread() {public void run() {//运行代码}}.start();//第二种Runnable r = new Runnable() {public void run() {//运行代码}};new Thread(r).start();
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- IOS注意事项(2)
- jar命令及jar包详解
- 【Android UI】 Shape详解 (GradientDrawable)
- No row with the given identifier exists
- 网站图标Icon添加方法
- 黑马程序员_多线程2
- ubuntu中安装gstreamer开发环境(转)
- 字符串的操作 a
- android银联支付
- “中国杯”游戏极限开发大赛 12月20日隆重开启
- Extjs 获取页面元素放到一个combox 中显示
- 原生AJAX调用四步曲:仅供初学者参考
- 信息系统项目管理师==之==项目管理9大管理过程知识点概要
- 数据读取之逻辑读简单解析--关于BUFFER CACHE