Java线程

一. FutureTask

单独使用Runnable时,无法获得返回值,并且Thread类只支持Runnable,所以添加了 FutureTask,Future 和 Callable 类。

单独使用Callable时,无法在新线程中(new Thread(Runnable r))使用,只能使用ExecutorService,于是有了 Future 可以根据 Callable 构建线程

由于 Future 只是一个接口,无法直接创建对象,因此有了 FutureTask

  1. 作用
  • FutureTask实现了Runnable和Future,兼顾两者优点,既可以使用ExecutorService,也可以使用Thread
  • 可以取消的异步的计算任务,它的计算是通过Callable实现的,它等价于可以携带结果的Runnable
  1. 实现接口
  • Runnable
  • Callable
    • 用于实现并行执行的接口。它与 Runnable 接口非常相似,但是它不返回任何值,而 Callable 必须在执行结束时返回一个值
  • Future
    • 封装并行调用的类,可以取消任务的执行,确定执行是否已成功完成或出错,以及其他操作

二. Callable接口 vs Runnable接口

RunnableCallable
核心方法run()方法call()方法
返回值
异常run()方法不可以声明抛出异常call()方法可以声明抛出异常
线程(池)executors、threadexecutors
相同点接口,调用Thread.start()启动线程接口,调用Thread.start()启动线程

三. ThreadPoolExecutor

线程池:

  1. 加快响应速度。消除了线程创建带来的延时
  2. 合理的利用CPU和内存。控制线程的数量,既不会因为线程太多导致内存溢出,也不会因为太少导致CPU资源的浪费
  3. 便于统一管理线程
// ThreadPoolExecutor 构造器
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

参数含义

  • 7个参数,其中前5个是必要参数,后两个(线程工厂和拒绝策略)可选。
参数类型含义
corePoolSizeint核心池大小,表示线程池维护线程的最少数量
maximumPoolSizeint最大池大小,表示线程池维护线程的最大数量
keepAliveTimelong线程池维护线程所允许的空闲时间
workQueueBlockingQueue阻塞队列,表示如果任务数量超过核心池大小,多余的任务添加到阻塞队列中
unitTimeUnit线程池维护线程所允许的空闲时间的单位
threadFactoryThreadFactory线程工厂,线程池需要新的线程时,生成新的线程
handlerRejectedExecutionHandler拒绝策略,线程池对拒绝任务的处理策略

四.volatile关键字

volatile相当于一个轻量级的sychronize,不会引起线程的上下文切换

  1. 作用:
  • 保证内存可见性,但不能保证变量的原子性

    • 线程A对一个volatile变量的修改,对于其它线程来说是可见的,即线程每次获取volatile变量的值都是最新的
    • 如:后缀++的操作,无法通过volatile保证结果准确性的,因为其不具有原子性
  • 禁止指令重排

  1. 举例:
class Resource implements Runnable {
	volatile public int i;                                                              
 	public  Resource(int _i){
    	i = _i;
 	}
 	public void run(){
		while(true){
     		if (i>0){
        		try{
             		Thread.sleep(200);
        		}
        		catch(Exception e){}
        		i--; // 不具备原子性
        		System.out.println(Thread.
        		currentThread().getName()+"  "+i);
    		}
    		else{
        		System.out.println(Thread.
        		currentThread().getName());
        		break;
    		}
  		}
	}
}

public class TestSecurity{
	public static void main(String[] args){
  		Resource m = new Resource(9);
  		Thread t1 = new Thread(m);
  		Thread t2 = new Thread(m);
  		t1.start();
  		t2.start();
	}
}
/* 
某次运行结果:
	Thread-0  7
	Thread-1  7
	Thread-1  6
	Thread-0  5
	Thread-1  4
	Thread-0  4
	Thread-0  3
	Thread-1  3
	Thread-1  2
	Thread-0  2
	Thread-1  1
	Thread-0  0
	Thread-0
	Thread-1  -1
	Thread-1
结果并不准确
*/

五. Java实现互斥的同步机制

监视器(monitor)和 synchronized

  1. 用法:
  • synchronized 代码块:监视器就是指定的对象
  • synchronized 方法:监视器就是 this 对象
  • synchronized 静态方法:监视器就是相应的类

ReentrantLock类

六. 线程应用

  1. 烧水泡茶最优工序

在这里插入图片描述

class MakeThread2 extends Thread{
    public void run() {
        System.out.println();
        System.out.print(this.getName() + ":             洗茶壶(1分钟)->");
        try {
            Thread.sleep(1000);
        }
        catch(Exception e) {
            System.out.println(e);
        }
        System.out.print("洗茶杯(2分钟)->");
        try {
            Thread.sleep(2000);
        }
        catch(Exception e) {
            System.out.println(e);
        }
        System.out.println("拿茶叶(1分钟)");
    }
}

class MakeThread1 extends Thread{
    MakeThread2 m2 = new MakeThread2();
    public void run() {
        System.out.print(this.getName() + ":洗水壶(1分钟)->");
        try {
            Thread.sleep(1000);
        }
        catch(Exception e) {
            System.out.println(e);
        }
        System.out.println("烧水(15分钟)->等待");
        System.out.print("                           |");

        m2.start();
        try {
            this.sleep(11000);
        }
        catch (InterruptedException e) {
            System.out.println(e);
        }
        System.out.println();
        System.out.println(this.getName() + ":泡茶,共用16分钟");
    }
}

public class Make{
    public static void main(String[] args) {
        MakeThread1 m1 = new MakeThread1();
        m1.start();

    }
}

运行结果:
在这里插入图片描述

  1. Java并发包的Lock及Conditon改写例9.11
import java.util.concurrent.locks.*;
class Account{
	volatile private int value;
    //布尔标志              
    volatile private boolean isMoney = false;   
    private final ReentrantLock lock = new ReentrantLock();
    // 存钱的 Condition 对象
    private Condition SaveCondition = lock.newCondition();
    // 取钱的 Condition 对象
    private Condition FetchCondition = lock.newCondition();

	void put(int i) {
		lock.lock(); //使用锁取代同步方法
		try{ 
			while(isMoney){
				try{ 
					SaveCondition.await(); //存钱线程等待
				} catch(Exception e){}
			}
			value = value + i; 
			System.out.println("存入"+i+" 账上金额为:"+value);
			isMoney = true;//设置标志
			FetchCondition.signal(); //唤醒等待资源的取钱线程
		} finally {
			lock.unlock();
		}	
	}
    
	int get(int i) { 
		lock.lock(); 
		try{
			while(!isMoney ){
				try { 
					FetchCondition.await(); //取钱线程等待
				} catch(Exception e){}
			}
			if (value>i)
				value = value - i;         
			else {  
				i = value;
				value = 0; 
			}
			System.out.println("取走"+i+" 账上金额为:"+value);
			isMoney = false;
			SaveCondition.signal(); //唤醒等待资源的存钱线程
			return i;                      
		} finally {
			lock.unlock();
		}
	}
}
  1. 生产者/消费者模式
/**
 * 代码来源:
 *		程序猿学社 - https://ithub.blog.csdn.net/
 */
public class Pile {
    //库存数量
    private  int sum=0;
    private int max=10;

    /**
     * 生产者
     */
    public synchronized  void pro(){
        while (sum == max){  //达到最大值说明库存已经满了,无法存放充电桩
            try {
                this.wait();    //需要等待消费者,消费后,才能生存
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        sum++;
        System.out.println(Thread.currentThread().getName()+":剩余充电桩数量为"+sum);
        this.notifyAll();   //通知消费者,我们库存有充电桩,赶紧来消费
    }

    /**
     * 消费者
     */
    public  synchronized  void consumer(){
        while (sum == 0){
            try {
                this.wait();  //说明库房,充电桩不够了,需要等待充电桩厂家,继续生产充电桩
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        sum --;
        System.out.println(Thread.currentThread().getName()+":剩余充电桩数量为"+sum);
        this.notifyAll();  //通知生产厂家,我已经消费了,你可以继续生产充电桩
    }
}

测试类:

/**
 * 代码来源:
 * 		程序猿学社 - https://ithub.blog.csdn.net/
 */
public class Demo1{
    public static void main(String[] args) {
        Pile pile = new Pile();

        for (int j = 0; j < 3; j++) {
            new Thread(()->{
                for (int i = 0; i < 15; i++) {
                    pile.pro();
                }
            },"生产者"+j).start();


            new Thread(()->{
                for (int i = 0; i < 15; i++) {
                    pile.consumer();
                }
            },"消费者"+j).start();
        }
    }
}

总结

​ 在整理博客的过程中参考了一些资料以及许多他人优秀的文章,就不一一列举,在此表示感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值