一.线程间的通信
1.多个线程操作共享资源,但是任务不一样
class Resource{
private int num = 1;
private boolean flag = false;
private String name;
public synchronized void set(String name){
if(flag){
try{
this.wait();
}catch(InterruptedException e){
}
}
this.name = name+num;
System.out.println(Thread.currentThread().getName()+"生产了"+this.name);
num++;
this.flag = true;
this.notify();
}
public synchronized void out(){
if(!flag){
try{
this.wait();
}catch(InterruptedException e){
}
}
System.out.println(Thread.currentThread().getName()+"消费了............"+this.name);
this.flag = false;
this.notify();
}
}
class Producer implements Runnable{
Resource r;
public Producer(Resource r) {
this.r = r;
}
@Override
public void run() {
while(true){
r.set("烤鸭");
}
}
}
public class Consumer implements Runnable{
Resource r;
public Consumer(Resource r) {
this.r = r;
}
@Override
public void run() {
while(true){
r.out();
}
}
}
public class MyThread {
public static void main(String[] args) {
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
wait、notify、notifyAll这些方法必须定义在同步中,因为这些方法是用来监视线程状态的,并且需要明确是哪一个锁上的线程。
2.jdk5.0
class Resourse{
private String name;
private int nums = 1;
private boolean flag = false;
ReentrantLock lock = new ReentrantLock();
Condition pro = lock.newCondition();
Condition con = lock.newCondition();
public void set(String name){
lock.lock();
try{
while(flag){
try{
pro.await();
}catch(InterruptedException e){
}
}
this.name = name+nums;
nums++;
System.out.println(Thread.currentThread().getName()+"生产了"+this.name);
flag = true;
con.signal();
}finally{
lock.unlock();
}
}
public void out(){
lock.lock();
try{
while(!flag){
try{
con.await();
}catch(InterruptedException e){
}
}
System.out.println(Thread.currentThread().getName()+"......消费了烤鸭......"+this.name);
flag = false;
pro.signal();
}finally{
lock.unlock();
}
}
}
class Producer implements Runnable{
Resourse r;
public Producer(Resourse r) {
this.r = r;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
r.set("烤鸭");
}
}
}
class Consumer implements Runnable{
Resourse r;
public Consumer(Resourse r) {
this.r = r;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
r.out();
}
}
}
public class ProducerConsumer {
public static void main(String[] args) {
Resourse r = new Resourse();
Producer p = new Producer(r);
Consumer c = new Consumer(r);
Thread t0 = new Thread(p);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
Thread t3 = new Thread(c);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
用Lock接口替代了同步关键字synchronized,将原来对获取锁,释放锁的操作(隐式)变为显示操作了。
用Condition接口替代了object的监视器方法,封装成了监视器对象,可以与任意锁进行组合。
二.线程调度
1.为什么使用
程序中的多个线程是并发执行的,在某个线程想要被执行就必须要获得cpu的执行权。jvm为线程分配cpu使用权的机制被称为线程的调度。
2.两种调度模型
- 分时调度模型:平均分配cpu时间片段,让线程轮流执行
- 抢占式调度模型:让线程优先级高的先运行,优先级相同的随机选择一个运行(java默认采用这种方式的调度模型)
3.线程优先级
public class MyThread implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"is inputing..."+i);
}
}
public static void main(String[] args) {
MyThread my = new MyThread();
Thread t0 = new Thread(my);
Thread t1 = new Thread(my);
t0.setPriority(1);
t0.setPriority(10);
t0.start();
t1.start();
}
}
用1-10来表示,10最高,可通过setPriority()来设置优先级,参数为1-10或者3个常量。
- 1 Thread.MIN_PRIORITY
- 5 Thread.NORM_PRIORITY
- 10 Thread.MAX_PRIORITY
4.线程的休眠
通过调用Thread.sleep()方法来让当前线程暂停运行,释放cpu执行权和执行资格,让别的线程先运行。
休眠时间超时,线程就进入就绪状态,重新具备cpu执行资格,在就绪线程池中等待cpu执行权。
5.线程让步
和sleep方法功能类似,都是让出线程的cpu执行权,区别在于yeild方法不会让线程经过阻塞状态,而是直接进入就绪状态。
public class MyThread implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"......is inputing......"+i);
if(i==10){
System.out.println("线程让步");
Thread.yield();
}
}
}
public static void main(String[] args) {
MyThread my = new MyThread();
Thread t0 = new Thread(my);
Thread t1 = new Thread(my);
t0.start();
t1.start();
}
}
6.线程插队
当正在运行的线程调用了其它线程的join方法时,调用者进入阻塞状态,当其它线程运行完毕,调用者进入就绪状态。
public class MyThread implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"......is inputing......"+i);
}
}
public static void main(String[] args) throws InterruptedException {
MyThread my = new MyThread();
Thread t0 = new Thread(my);
t0.start();
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"......is inputing......"+i);
if(i==10){
System.out.println("线程插队");
t0.join();
}
}
}
}