黑马程序员_多线程2

原创 2013年12月05日 15:58:05

------- 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();


黑马程序员—黑马的学习环境没有亲身经历的人是很难体会的!!!

文章来源:黑马程序员,黑马论坛     公元2013年1月10号我拖着沉重的行李箱和对未来的憧憬来到了黑马,公元2013年6月7号我怀抱着满满的知识和对老师的不舍离开了黑马。到现在离开黑马也有一个...
  • heima_28
  • heima_28
  • 2014年08月26日 15:16
  • 1399

关于我在黑马程序员培训毕业后的亲身体验

首先申明:我本人已经于2016年5月份在广州传智播客java培训完毕业,和黑马程序员官网没有任何的利益往来,也没有人出钱给我帮他们做软文推广,这是我在黑马程序员的亲身体验,不存在虚构。...
  • wjycgl
  • wjycgl
  • 2017年04月20日 15:27
  • 1501

黑马程序员:3分钟带你读懂C/C++学习路线

http://blog.csdn.net/itcast_cn/article/details/52302287         随着互联网及互联网+深入蓬勃的发展,经过40余年的时间...
  • baidu_26352053
  • baidu_26352053
  • 2016年12月10日 16:09
  • 1712

黑马程序员_面向对象_多线程2

----------- android培训、java培训、期待与您交流!------------ 1、为什么wait(),notify(),notifyAll()没有定义在Thread里面而定义在了...
  • zzzx081135
  • zzzx081135
  • 2014年05月05日 16:01
  • 227

黑马程序员_Java基础_多线程2

一、多线程(线程间通信-示例代码) [java] view plaincopy /*  线程间通讯:  其实就是多个线程在操作同一个资源,但是操作的动作...
  • mantuntun123
  • mantuntun123
  • 2014年12月14日 12:03
  • 177

黑马程序员_Java基础_多线程2

------- android培训、java培训、期待与您交流! ---------- 一、多线程(线程间通信-示例代码) /* 线程间通讯: 其实就是多个线程在操作同一个资源,但是操作的动作...
  • yangcheng91
  • yangcheng91
  • 2012年08月10日 19:22
  • 238

黑马程序员——12,多线程(2)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------               黑马程序员——12,多线程(2)   //线程之间的通信 //就是多...
  • dangaodeaiyi
  • dangaodeaiyi
  • 2015年07月29日 00:31
  • 581

黑马程序员_多线程_2

——- android培训、java培训、期待与您交流! ———-计算机CPU的运行原理 我们电脑上有很多的程序在同时进行,就好像cpu在同时处理这所以程序一样。但是,在一个时刻,单核的cp...
  • wu_zida
  • wu_zida
  • 2015年06月24日 17:57
  • 162

黑马程序员----[20150505][多线程2]

------   Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 第二讲  多线程 1.线程间通信-示例代码 线程间通讯: 其实就是多个线程在操作同...
  • ninchen
  • ninchen
  • 2015年05月05日 19:04
  • 159

黑马程序员_多线程(2) 传统线程通信&Condtion

-------android培训、java培训、期待与您交流! ---------- 一.线程通信         生产者与消费者         线程间通信。         等待/...
  • johese
  • johese
  • 2013年03月14日 13:16
  • 337
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:黑马程序员_多线程2
举报原因:
原因补充:

(最多只允许输入30个字)