线程休眠、礼让、等待

线程的状态

线程休眠、礼让、等待_第1张图片

线程休眠、礼让、等待_第2张图片

线程中的方法

boolean isAlive()   测试线程是否处于活动状态
setPriority(int newPriority) 更改线程优先级
static void sleep(long millis)   让指定线程休眠指定的毫秒数
void join() 线程插队 强制执行
static void yield() 线程礼让
void interrupt() 线程中断
wait() 线程等待
notify()  notifyAll() 线程唤醒

线程休眠

1.Thread.sleep(时间) 指定当前线程阻塞的 毫秒数;

2.线程休眠存在异常,所以要捕获异常

3.sleep时间达到后线程进入就绪状态

4.每个对象都有一个锁,sleep不会释放锁,但会让出CPU

线程礼让

1. Thred.yield()  让当前执行的线程暂停,但不阻塞,

2.使线程从运行状态转为就绪状态

3.让CPU重新调度,礼让不一定成功。

4.yield会使当前线程重回到可执行状态,等待cpu的调度,不释放锁

线程插队

1.Thread.jion()  调用此方法的线程强制执行,把调用此方法的线程运行结束后,在运行其他线程

2.当前线程调用 某线程.join()时会使当前线程等待某线程执行完毕再结束,底层调用了wait,释放锁

测试代码

package com.example.demo.therad;

public class JionDemo implements Runnable{

	public void run() {
		for(int i=0;i<20;i++) {
			System.out.println("VIP:"+i);			
		}
      System.out.println("VIP运行完了");
		
	}

}
public static void main(String[] args) throws Exception{
		JionDemo jionDemo=new JionDemo();
		Thread thread=new Thread(jionDemo);
		thread.start();
		for(int i=0;i<=30;i++) {
			if (i==10) {
				thread.join();				
			}
			System.out.println("普通客户运行:"+i);
			
			
		}

结果

普通客户运行:0
VIP:0
普通客户运行:1
VIP:1
普通客户运行:2
普通客户运行:3
普通客户运行:4
普通客户运行:5
普通客户运行:6
VIP:2
普通客户运行:7
普通客户运行:8
普通客户运行:9
VIP:3
VIP:4
VIP:5
VIP:6
VIP:7
VIP:8
VIP:9
VIP:10
VIP:11
VIP:12
VIP:13
VIP:14
VIP:15
VIP:16
VIP:17
VIP:18
VIP:19
VIP运行完了
普通客户运行:10
普通客户运行:11
普通客户运行:12
普通客户运行:13
普通客户运行:14
普通客户运行:15
普通客户运行:16
普通客户运行:17
普通客户运行:18
普通客户运行:19
普通客户运行:20
普通客户运行:21
普通客户运行:22
普通客户运行:23
普通客户运行:24
普通客户运行:25
普通客户运行:26
普通客户运行:27
普通客户运行:28
普通客户运行:29
普通客户运行:30

线程等待

1.wait()方法 使线程一直等待,直到有其他线程通知唤醒

2.线程等待会释放锁

3.唤醒等待线程 用notify(唤醒一个等待线程)notifyAll 唤醒所有的等待线程

4,使用wait(long m)方法 wait方法如果在毫秒值结束之后 还没有被notify唤醒 就会自动醒来 线程睡醒进入到Runanle/Blocked状态

5.wait与notify、notifyAll必须配合synchronized使用,因为调用之前必须持有锁,wait会立即释放锁,notify则是同步块执行完了才释放

6.唤醒当前对象锁的等待线程使用notify或notifyAll方法,也必须拥有相同的对象锁,否则也会抛出IllegalMonitorStateException异常。

线程的等待还可以使用

ReenTrantLock
Condtion condition=lock.newCondition
await() 等待
singal() 唤醒

Condition类提供,而Condition对象由new ReentLock().newCondition()获得,与wait和notify相同,因为使用Lock锁后无法使用wait方法

案例生产者 消费者

package com.example.demo.therad;
//生产者
public class Provider implements Runnable {
	
	private ChickenContainer chickenContainer;
	
	
	
	public Provider(ChickenContainer chickenContainer) {
		this.chickenContainer=chickenContainer;
		
	}
	
	public void run() {
		for (int i = 1; i <=20; i++) {
			chickenContainer.push(new Chick(i));
		}		
	}

}
package com.example.demo.therad;
//消费者


public class Consumer implements Runnable {	
	private ChickenContainer chickenContainer;			
	public Consumer(ChickenContainer chickenContainer) {
		this.chickenContainer=chickenContainer;		
	}
	public void run() {
		for (int i = 1; i <=20; i++) {
			chickenContainer.pop(new Chick(i));
		}		
	}
}
package com.example.demo.therad;
//生产者 消费者 容器

import java.util.LinkedList;

public class ChickenContainer {
	
	LinkedList list=new LinkedList();
	private int num = 10;//容器大小
	
	//生产者生产
	public synchronized void push(Chick chick) {
		
		if (list.size()== num) {
			//如果容器已满 生产者等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}			
		}
		//通知消费者 消费
		System.out.println("生产者生产了第:"+chick.getId()+"只");
		list.add(chick);
		this.notifyAll();
		
	}
	//消费者 消费
	public synchronized void pop(Chick chick) {
		
		if (list.isEmpty()) {
			//容器为空 消费者等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		//通知 生产者 生产
		
		System.out.println("消费者消费了第:"+chick.getId()+"只");
		list.remove(0);
		this.notifyAll();
	}
	
}
	

测试

public static void main(String[] args) throws Exception{
		ChickenContainer chickenContainer=new ChickenContainer();
	    Provider provider=new Provider(chickenContainer);
	    Consumer consumer=new Consumer(chickenContainer);
	    Thread proThread=new Thread(provider);
	    Thread conThread=new Thread(consumer);
	    proThread.start();
	    conThread.start();		
	}

运行结果

生产者生产了第:1只
生产者生产了第:2只
生产者生产了第:3只
生产者生产了第:4只
生产者生产了第:5只
生产者生产了第:6只
生产者生产了第:7只
生产者生产了第:8只
生产者生产了第:9只
生产者生产了第:10只
消费者消费了第:1只
消费者消费了第:2只
消费者消费了第:3只
消费者消费了第:4只
消费者消费了第:5只
消费者消费了第:6只
消费者消费了第:7只
消费者消费了第:8只
消费者消费了第:9只
消费者消费了第:10只
生产者生产了第:11只
生产者生产了第:12只
生产者生产了第:13只
生产者生产了第:14只
生产者生产了第:15只
生产者生产了第:16只
生产者生产了第:17只
生产者生产了第:18只
生产者生产了第:19只
生产者生产了第:20只
消费者消费了第:11只
消费者消费了第:12只
消费者消费了第:13只
消费者消费了第:14只
消费者消费了第:15只
消费者消费了第:16只
消费者消费了第:17只
消费者消费了第:18只
消费者消费了第:19只
消费者消费了第:20只
Interrupt 方法结束线程
使用 interrupt()方法来中断线程有两种情况:
1. 线程处于阻塞状态:如使用了 sleep,同步锁的 wait,socket 中的 receiver,accept 等方法时,
会使线程处于阻塞状态。当调用线程的 interrupt()方法时,会抛出 InterruptException 异常。
阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后 break 跳出循环状态,从而让
我们有机会结束这个线程的执行。 通常很多人认为只要调用 interrupt 方法线程就会结束,实
际上是错的, 一定要先捕获 InterruptedException 异常之后通过 break 来跳出循环,才能正
常结束 run 方法
2. 线程未处于阻塞状态:使用 isInterrupted()判断线程的中断标志来退出循环。当使用
interrupt()方法时,中断标志就会置 true,和使用自定义的标志来控制循环是一样的道理。
public class ThreadSafe extends Thread {
 
public void run() { 
 
while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出
 
       try{
 
 
         Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出
 
      }catch(InterruptedException e){
 
         e.printStackTrace();
         break;//捕获到异常之后,执行 break 跳出循环
         }
     }
   } 
}

interrupt()、interrupted()和isInterrupted()的区别

  • interrupt()方法:表示可以中断线程,实际上只是给线程设置一个中断标志,将中断标志置 true,,但是线程依旧会执行。
  • interrupted()方法:Thread类的静态方法。检查当前线程的中断标志,返回一个boolean并清除中断状态,如果线程的中断标志位是true,那么调用interrupted()方法后中断标志位将改为false,即连续两次调用的返回结果不一样,因为第二次调用的时候线程的中断状态已经被清除,会返回一个false。
  • isInterrupted()方法:测试线程是否被中断,不会清除中断状态。

    使用  isInterrupted()方法  

class TestThread extends Thread{
    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + "正在打印 i = " + i);
        }
    }
}
 
public class TestInterrupted {
    public static void main(String[] args) {
        TestThread  mt = new TestThread();
        mt.start();
        mt.interrupt();
        System.out.println("第一次调用isInterrupted()方法,值为:" + mt.isInterrupted());
        System.out.println("第二次调用isInterrupted()方法,值为:" + mt.isInterrupted());
        System.out.println("thread是否存活:" + mt.isAlive());
    }
}

结构:线程休眠、礼让、等待_第3张图片

 isInterrupted()方法:测试线程是否被中断,不会清除中断状态。

使用interrupted()方法

public class TestInterrupted {
    public static void main(String[] args) {
        Thread.currentThread().interrupt();
        System.out.println("第一次调用isInterrupted()方法,值为:" + Thread.currentThread().isInterrupted());
        System.out.println("调用interrupted()方法,值为:" + Thread.currentThread().interrupted());
        System.out.println("调用interrupted()方法,值为:" +Thread.currentThread().interrupted());
    }
}

线程休眠、礼让、等待_第4张图片

 结果可以看到第二次调用interrupted()方法返回false

线程状态。
线程可以处于以下状态之一:

NEW
尚未启动的线程处于此状态。
RUNNABLE
在Java虚拟机中执行的线程处于此状态。
BLOCKED
被阻塞等待监视器锁定的线程处于此状态。
WAITING
正在等待另一个线程执行特定动作的线程处于此状态。
TIMED_WAITING
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
TERMINATED
已退出的线程处于此状态。
 

你可能感兴趣的:(java,开发语言)