java自定义线程池池,线程池使用及自定义线程池

一 案例引申

编写代码同时只允许五个线程并发访问(以下文的函数为例子)

private static void method() {

System.out.println("ThreadName" + Thread.currentThread().getName() + "进来了");

Thread.sleep(2000);

System.out.println("ThreadName" + Thread.currentThread().getName() + "出去了");

}

思考:

1 若果使用 synchronized的话避免了并发安全问题,但是不满足题目的要求,因为题目要求一次让五个线程访问,使用锁的时候一次只能访问一个。

2 解决思路:使用信号量或者使用线程池

二 信号量的简单使用(了解)

package ThreadPool;

import java.util.concurrent.*;

import java.util.concurrent.atomic.AtomicInteger;

/**

* Create by SunnyDay on 2018/11/27

*/

public class ThreadPoolDemo {

//信号量 Doug Lea 大牛写的(concurrent并发包下面的东西都是他写的) 参数控制并发线程的个数

private static Semaphore semaphore = new Semaphore(5);

public static void main(String[] args) {

for (int i = 0; i < 100; i++) {

new Thread(new Runnable() {

@Override

public void run() {

try {

method();

} catch (InterruptedException e) {

}

}

}).start();

}

private static void method() throws InterruptedException {

// 首先获取一把锁

semaphore.acquire();

System.out.println("ThreadName" + Thread.currentThread().getName() + "进来了");

Thread.sleep(2000);

System.out.println("ThreadName" + Thread.currentThread().getName() + "出去了");

// 释放锁

semaphore.release();

}

三 使用线程池解决(了解)

package ThreadPool;

import java.util.concurrent.Executor;

import java.util.concurrent.Executors;

/**

* Create by SunnyDay on 2018/11/27

* 使用线程池解决

*/

public class ThreadPool {

/**

* java 提供了线程池的创建工具类( Executors),

* 我们可以通过工具类创建不同的线程池

*/

private static Executor executor = Executors.newCachedThreadPool();//缓冲线程池

private static Executor executor2 = Executors.newFixedThreadPool(5);//固定线程池

private static Executor executor3 = Executors.newScheduledThreadPool(5);//计划任务线程池

private static Executor executor4 = Executors.newSingleThreadExecutor();//单个线程池(池中只有一个线程)

public static void main(String[] args) {

for (int i = 0; i < 100; i++) {

// 线程池的简单使用(十分简单) 调用execute方法传递参数类型为runnable类型即可

executor2.execute(new Runnable() {

@Override

public void run() {

try {

method();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

}

}

private static void method() throws InterruptedException {

System.out.println("ThreadName" + Thread.currentThread().getName() + "进来了");

Thread.sleep(2000);

System.out.println("ThreadName" + Thread.currentThread().getName() + "出去了");

}

}

四 自定义线程池

1 小发现

/**

* 查看随便几个个线程池的源码:

* public static ExecutorService newCachedThreadPool() {

* return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

* 60L, TimeUnit.SECONDS,

* new SynchronousQueue());

* }

*

* 发现都是对线程池类(ThreadPoolExecutor)进行了简单的封装(传的参数不一致)

*/

2 ThreadPoolExecutor构造( 以6个参数的为例子)

* @param corePoolSize 核心池大小 int

* @param maximumPoolSize 最大池大小 int

* @param keepAliveTime 保活时间 long(任务完成后要销毁的延时)

* @param unit 时间单位 决定参数3的单位,枚举类型的时间单位

* @param workQueue 工作队列 用于存储任务的工作队列(BlockingQueue接口类型)

* @param threadFactory 线程工厂 用于创建线程

*

* */

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue,

ThreadFactory threadFactory) {

this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

threadFactory, defaultHandler);

}

3 自定义实现案例

package ThreadPool;

import java.util.concurrent.*;

import java.util.concurrent.atomic.AtomicInteger;

/**

* Create by SunnyDay on 2018/11/27

*/

public class ThreadPoolDemo {

public static void main(String[] args) {

/**手写线程池

* @param corePoolSize 核心池大小 int

* @param maximumPoolSize 最大池大小 int

* @param keepAliveTime 保活时间 long(任务完成后要销毁的延时)

* @param unit 时间单位 决定参数3的单位,枚举类型的时间单位

* @param workQueue 工作队列 用于存储任务的工作队列(BlockingQueue接口类型)

* @param threadFactory 线程工厂 用于创建线程

*

*线程不是越多越好,google工程师推荐 线程个数=cpu核心数+1(例如四核的开5个线程最好)

* */

// 参数任务上限

LinkedBlockingQueue blockingQueue = new LinkedBlockingQueue<>(100);

ThreadFactory threadFactory = new ThreadFactory() {

// int i = 0; 用并发安全的包装类

AtomicInteger atomicInteger = new AtomicInteger(1);

@Override

public Thread newThread(Runnable r) {

//创建线程 吧任务传进来

Thread thread = new Thread(r);

// 给线程起个名字

thread.setName("MyThread" + atomicInteger.getAndIncrement());

return thread;

}

};

ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 1, TimeUnit.SECONDS, blockingQueue, threadFactory);

for (int i = 0; i < 100; i++) {

pool.execute(new Runnable() {

@Override

public void run() {

try {

method();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

}

}

/**

* 编写代码(如下文的函数)同时只允许五个线程并发访问:

*

* 1 若果使用 synchronized的话避免了并发安全问题,但是不满足题目的要求,

* 因为题目要求一次让五个线程访问,使用锁的时候一次只能访问一个。

* 2 解决思路:使用信号量或者使用线程池

*

* 3 自己手动封装线程池(明白启动策略)

*/

private static void method() throws InterruptedException {

System.out.println("ThreadName" + Thread.currentThread().getName() + "进来了");

Thread.sleep(2000);

System.out.println("ThreadName" + Thread.currentThread().getName() + "出去了");

}

}

五 线程池补充

1 启动策略草图

d7d41e1ae40d

image.png

2 流程图(摘抄)

d7d41e1ae40d

image.png

六 总结

通过上面的总结相信对线程池的概念,使用,启动策略,大致的有了一些了解,但是这些还是不够的,想要深入了解还需我们不懈的努力探讨!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值