多线程
概念
三个概念:
① 程序:软件。数据与指令的集合。
② 进程:正在执行的程序。
③ 线程:进程中的多条执行路径。
两个概念:
① 并发:在某一个时间段内,都有执行。
② 并行:在同一时刻,同时执行。
多线程的好处:
提高了程序的执行效率。
线程也不能无限开启,必须要有度。
创建线程的方式
① 继承 Thread
② 实现 Runnable
③ 实现 Callable
线程创建方式一
继承:
Thread类:
java提供的线程类,运行线程并发执行。
一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法
需要调用start方法开启线程
代码
package com.demo;
public class 线程创建方式一 {
public static void main(String[] args) throws InterruptedException {
AThread at = new AThread();
at.start();
for (int i = 0; i < 1000; i++) {
System.out.println("main+=="+i);
}
}
}
class AThread extends Thread{
@Override
public void run() {
for (int i = 0; i <1000 ; i++) {
System.out.println("AThread================="+i);
};
}
}
线程执行的调度机制
抢占式执行。cpu的时间片
线程的执行结果是未知的。
线程的执行原理
线程创建的方式二
实现Runnable
实现接口中的run方法。
在创建对象时,需要通过start方法才能开启线程。
Thread(Runnable target) 该构造可以把Runnable接口对象转换成线程。进而调用start方法。
注意:继承和实现两种形式在实际开发中,使用?
继承的特点:单继承 多重继承
实现的特点:多继承 多重继承 多实现。
现实开发中,使用接口的实现的形式较多,该方式比继承更灵活。
代码
package com.demo;
/**
实现Runnable
实现接口中的run方法。
在创建对象时,需要通过start方法才能开启线程。
Thread(Runnable target) 该构造可以把Runnable接口对象转换成线程。进而调用start方法。
*/
public class 线程创建方式二 {
public static void main(String[] args) {
ARunnable ar = new ARunnable();
// ar -->Thread
Thread at = new Thread(ar);
at.start();
for (int i = 0; i < 1000; i++) {
System.out.println("main+=="+i);
}
}
}
class ARunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i <1000 ; i++) {
System.out.println("ARunnable================="+i);
};
}
}
线程创建的方式三
1.实现接口Callable:
需要线程返回线程的执行结果。
call()
由于Thread中没有直接接收Callable的参数的构造方法,可以通过FutureTask(Callable
callable)
进行线程对象的创建。
2.FutureTask常用方法:
get() 获取线程的执行结果
代码
package com.demo;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
1.实现接口Callable:
需要线程返回线程的执行结果。
call()
由于Thread中没有直接接收Callable的参数的构造方法,可以通过FutureTask(Callable<V> callable)
进行线程对象的创建。
2.FutureTask常用方法:
get() 获取线程的执行结果
*/
public class 线程创建方式三 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ACallable ab = new ACallable();
//转线程对象
FutureTask<String> task = new FutureTask<>(ab);
Thread at = new Thread(task);
at.start();
System.out.println(task.get()+"=======================================");
for (int i = 0; i < 200; i++) {
System.out.println("main+=="+i);
}
}
}
class ACallable implements Callable<String>{
@Override
public String call() throws Exception {
for (int i = 0; i <100; i++) {
System.out.println("======================Acallable"+i);
}
return "这是一个线程的执行结果";
}
}
总结
线程创建:
① 继承Thread类
② 实现Runnable接口
③ 实现Callable接口
线程执行的调度机制
抢占式执行。cpu的时间片
线程的执行结果是未知的。
线程的执行原理
线程的常见方法
Thread
线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。
线程常见方法
1.常见方法:
① currentThread() 返回当前线程对象:不是线程体系的类,还想调用线程的方法时。
main方法 :main线程 主线程
② getName() /setName(String name) 返回/设置当前线程名称
默认线程的名称:
Thread-index :index从0开始
③ getPriority()/setPriority(int newPriority)返回/设置线程的优先级。
(***) 线程的优先级:高优先级的执行要高于低优先级的。
1>MAX_PRIORITY 最高优先级 10
2>MIN_PRIORITY 最小优先级 1
3>NORM_PRIORITY 默认优先级 5
代码
package com.demo;
/**
1.常见方法:
① currentThread() 返回当前线程对象:不是线程体系的类,还想调用线程的方法时。
main方法 :main线程 主线程
② getName() /setName(String name) 返回/设置当前线程名称
默认线程的名称:
Thread-index :index从0开始
③ getPriority()/setPriority(int newPriority)返回/设置线程的优先级。
(***) 线程的优先级:高优先级的执行要高于低优先级的。
1>MAX_PRIORITY 最高优先级 10
2>MIN_PRIORITY 最小优先级 1
3>NORM_PRIORITY 默认优先级 5
*/
public class 线程常见方法 {
public static void main(String[] args) {
/* AThread at = new AThread();
at.start();
AThread at1 = new AThread();
at1.start();*/
System.out.println(Thread.currentThread().getName());
System.out.println(Thread.currentThread().getPriority());
}
}
class AThread extends Thread{
@Override
public void run() {
System.out.println(getName());
}
}
线程常见方法一
1.interrupt()中断线程。标记线程是否是中断。
2.interrupted() 判断线程是否中断。
代码
package com.demo;
/**
1.interrupt()中断线程。标记线程是否是中断。
2.interrupted() 判断线程是否中断。
*/
public class 线程常见方法一 {
public static void main(String[] args) {
BThread bt = new BThread();
bt.start();
}
}
class BThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i == 5){
interrupt();
}
System.out.println(i+"==============="+interrupted());
}
}
}
线程常见方法二
1.守护线程:setDaemon(boolean on)/isDaemon() 设置/判断是否为守护线程
注意: 参数为true表示是一个守护线程。
在线程开启之前设置为守护线程。
2.线程分类:
① 用户线程
② 守护线程: 为用户线程提供便捷服务的线程。用户线程一旦结束,守护线程也会随之结
束。
代码
package com.demo;
/**
1.守护线程:setDaemon(boolean on)/isDaemon() 设置/判断是否为守护线程
注意: 参数为true表示是一个守护线程。
在线程开启之前设置为守护线程。
2.线程分类:
① 用户线程
② 守护线程: 为用户线程提供便捷服务的线程。用户线程一旦结束,守护线程也会随之结束。
*/
public class 线程常见方法三 {
public static void main(String[] args) {
CThread ct = new CThread();
//线程开启之前 设置
ct.setDaemon(true);
ct.start();
for (int i = 0; i <10 ; i++) {
System.out.println("=============main"+i);
}
}
}
class CThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("====+CThread+=="+i);
}
}
}
线程常见方法三
1.join()/join(ms) 等待线程的终止
注意: 线程开启之后调用。
相当于方法调用,调用run方法。
代码
package com.demo;
/**
1.join()/join(ms) 等待线程的终止
注意: 线程开启之后调用。
相当于方法调用,调用run方法。
*/
public class 线程常见方式四 {
public static void main(String[] args) throws InterruptedException {
DThread dt = new DThread();
dt.start();
dt.join();
for (int i = 0; i < 100; i++) {
System.out.println("main+======================================"+i);
}
}
}
class DThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("DThread +======"+ i);
}
}
}
线程常见方法四
(***) 1.sleep(long millis) 休眠
(*)2.yield() 线程的让步,暂停当前线程的执行,转而执行其他线程
package com.demo;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
(***) 1.sleep(long millis) 休眠
(*)2.yield() 线程的让步,暂停当前线程的执行,转而执行其他线程。
*/
public class 线程常见方法五 {
public static void main(String[] args) throws InterruptedException {
/*for (int i = 0; i < 100; i++) {
System.out.println(i);
Thread.sleep(100);
}*/
//打印时间
/* SimpleDateFormat sf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
while (true){
Date date = new Date();
System.out.println(sf.format(date));
Thread.sleep(1000);
}*/
// System.out.println(Thread.currentThread().toString());
// yield()
MThread m = new MThread();
m.start();
for (int i = 0; i < 10000; i++) {
System.out.println("main+============================"+i);
}
}
}
class MThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
if(i%2 == 0){
yield();
}
System.out.println("===="+i);
}
}
}
多线程的安全问题
概述
(***)多线程的安全问题:当多个线程,共同操作多个共享数据时,由于多个线程的同时操作,导致
程序运行的结果与预期的结果不一致,该现象称为多线程的安全问题。
解决
方式:
① 同步
② 线程的通信: wait() notify() notifyAll()
同步
也称为加锁
关键字:synchronized
① 分类:
同步方法:
[权限修饰符] synchronized 返回值类型 方法名称(参数列表){}
同步代码块
synchronized(锁对象){
}
锁对象:可以是任意对象。
常见的锁对象:
① 对象锁: 对象
② this锁: this
③ 静态锁: 静态成员
④ 类锁: 类名/数据类型 .class
代码
package com.demo;
/**
1.多线程的安全问题:
账户取款操作。
*/
public class 多线程的安全问题 {
public static void main(String[] args) {
BankAccount ba = new BankAccount();
Thread t = new Thread(ba);
Thread t1 = new Thread(ba);
t.setName("张三");
t1.setName("李思");
t.start();
t1.start();
}
}
class BankAccount implements Runnable{
double balance = 1000;//余额
Object o = new Object();
static Double d = new Double(12.3);
@Override
public /*synchronized*/ void run() {
//同步代码块 任意对象:锁对象:要求对所有的线程对象有效 ,共享。
// synchronized (o) {//对象锁
// synchronized (this) {//this锁
// synchronized (d) {//静态锁:静态成员
synchronized (BankAccount.class) {//类锁
if(balance>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
balance -=1000;
System.out.println(Thread.currentThread().getName()+"取款后,金额为:"+ balance);
}else{
System.out.println(Thread.currentThread().getName()+"余额不足");
}
}
}
}
继承关系下的同步方式
多线程的安全问题
1.解决多线程的安全问题:同步
2.同步注意事项:
又叫加锁:
1》同步方法
2》同步代码块
3.同步的前提:
① 必须存在多线程的安全问题
② 同步时,锁必须是唯一的,共享的,所有线程共享同一把锁。
4.同步方法:
静态方法 :相当于 同步代码块中的类锁
[权限修饰符] static synchronized 返回值类型 方法名称(参数列表){}
非静态方法: 相当于 同步代码块中的this
[权限修饰符] synchronized 返回值类型 方法名称(参数列表){}
注意:
一般不建议 synchronized 加载run方法上。
5.同步代码块:
锁对象:
① this锁
② 任意对象
③ 类锁: .class
④ 静态锁:静态对象
代码
package com.demo;
/**
1.多线程? 安全问题?:
① 多个线程
② 共享数据
③ 共同访问共享数据
2.同步 又叫加锁:
① 保证有多线程的安全问题
② 保证锁唯一,所有线程对象共享同一把锁。
*/
public class 多线程的安全问题继承方式 {
public static void main(String[] args) {
BankAccount ba = new BankAccount();
BankAccount ba1 = new BankAccount();
ba.setName("张三");
ba1.setName("李思");
ba.start();
ba1.start();
}
}
class BankAccount extends Thread{
static double balance = 1000;
static Object o = new Object();
@Override
public /*synchronized */void run() {
// synchronized (BankAccount.class) {
synchronized (o) {
if (balance>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
balance -= 1000;
System.out.println(getName() + "取款后,余额为:"+balance);
}else{
System.out.println(getName()+"余额不足");
}
}
/*fun();
System.out.println("==============");*/
}
/*public static synchronized void fun(){
if (balance>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
balance -= 1000;
System.out.println(getName() + "取款后,余额为:"+balance);
}else{
System.out.println(getName()+"余额不足");
}
}*/
}
Lock锁
概念
Lock接口。
比使用 synchronized 方法和语句可获得的更广泛的锁定操作
创建对象:
使用的是子类ReentrantLock。
常用方法
① lock :获取锁
② unlock:释放锁
代码
package com.demo;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Lock锁 {
public static void main(String[] args) {
BA ba = new BA();
Thread t = new Thread(ba);
Thread t1 = new Thread(ba);
t.start();
t1.start();
}
}
class BA implements Runnable{
Lock lock = new ReentrantLock();
double balance = 1000;
@Override
public void run() {
//加锁
lock.lock();
if (balance>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
balance -= 1000;
System.out.println(Thread.currentThread().getName()+"取款后,余额为:"+balance);
}else{
System.out.println(Thread.currentThread().getName()+"余额不足!!!");
}
//释放锁
lock.unlock();
System.out.println("==============");
}
}
死锁
概念
DeadLock 死锁:
(***) 解决了多线程安全问题的同步线程,如果访问的是互斥的共享资源(互斥:多个共享资源,访问
顺序相反。),由于互斥访问,造成的资源锁死现象,称为死锁。
死锁现象
哲学家餐桌问题:
代码
package com.demo;
public class 死锁 {
public static void main(String[] args) {
AThread at = new AThread();
AThread at1 = new AThread();
at.flag = true;
at.start();
at1.start();
}
}
class AThread extends Thread{
static Object o = new Object();
static Object o1 = new Object();
boolean flag ;
@Override
public void run() {
if (flag){
synchronized (o){
System.out.println("执行了o......1");
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o1){
System.out.println("执行了o1....1");
}
}
}else{
synchronized (o1){
System.out.println("执行了o1......2");
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o){
System.out.println("执行了o....2");
}
}
}
}
}
查看死锁的工具
jstack 查看jvm的内存的运行状况。
格式:
jstack PID号
生产者和消费者模式
解决线程安全问题的方式
线程的通信:
可以实现多个线程之间的交互。
线程生命周期/线程的状态
线程的生命周期
新建状态:创建对象
就绪状态:start方法被调用。
运行状态:抢到了cpu时间片
消亡状态: 执行完毕
阻塞状态:在运行过程中,遇到的 wait、join、sleep等。
单例设计模式(饿汉式/懒汉式)
设计模式
java中有常见23种设计模式: 模板设计模式
单例:一个类中就只有一个对象。
实例化:创建对象
单例设计模式(饿汉式)
步骤:
① 私有构造方法
② 在该类中声明一个属性,该属性的数据类型就是该类,修饰符用 private static修饰。
③ 提供一个public static的get方法,对外提供该对象。
代码
package com.demo;
public class 单例设计模式 {
public static void main(String[] args) {
/* A a = new A();
A a1 = new A();
A a2 = new A();
A a3 = new A();
SingleTon s = new SingleTon();*/
SingleTon s = SingleTon.getInstance();
SingleTon s1 = SingleTon.getInstance();
System.out.println(s == s1);
}
}
class A{}
//饿汉式
class SingleTon{
private SingleTon(){}
private static SingleTon instance =new SingleTon();
public static SingleTon getInstance (){
return instance;
}
public static void fun(){}
}
懒汉式
1.由于饿汉式无论是否使用单例对象,都会创建该对象,为了进行改进,引入了懒汉式。
2.在实际开发中,使用饿汉式比懒汉式更多,
尽管饿汉式可能造成资源的浪费,但是懒汉式有线程安全问题的。
所以,考虑线程安全问题的前提下,使用饿汉式居多。如果要使用懒汉式,必须要进行线程安全问题的解决。加同步。
代码
package com.demo;
/**
1.由于饿汉式无论是否使用单例对象,都会创建该对象,为了进行改进,引入了懒汉式。
2.在实际开发中,使用饿汉式比懒汉式更多,
尽管饿汉式可能造成资源的浪费,但是懒汉式有线程安全问题的。
所以,考虑线程安全问题的前提下,使用饿汉式居多。如果要使用懒汉式,必须要进行线程安全问题的解决。加同步。
*/
public class 单例设计模式 {
public static void main(String[] args) {
SingleTon s = SingleTon.getInstance();
SingleTon s1 = SingleTon.getInstance();
System.out.println(s == s1);
}
}
//懒汉式
class SingleTon{
private SingleTon(){}
private static SingleTon instance ;
public static SingleTon getInstance(){
if (instance == null) {
synchronized (SingleTon.class) {
if (instance == null){
instance = new SingleTon();
}
}
}
return instance;
}
}
枚举
概念
1.枚举:有穷序列集。一一列举
2.案例:
性别: 数据类型 int 0 1 12
细节
1.1.5jdk引入了枚举
2.关键字 :enum 枚举类关键字 用法同class
3.枚举类第一行必须是该类对象的名称,多个之间用逗号隔开。
4.枚举类:本质: 类。
① 构造方法:有 并且是私有的。
② 属性:
③ 方法
④ 抽象方法
代码
package com.demo;
/**
1.1.5jdk引入了枚举
2.关键字 :enum 枚举类关键字 用法同class
3.枚举类第一行必须是该类对象的名称,多个之间用逗号隔开。
4.枚举类:本质: 类。
① 构造方法:有 并且是私有的。
② 属性:
③ 方法
④ 抽象方法
*/
public class 枚举 {
public static void main(String[] args) {
Student st = new Student();
st.sex = Sex.MALE;
st.sex = Sex.FEMALE;
//面向对象 对象.方法/属性
Sex.MALE.fun();
//红灯的行为
Traffic.RED.action();
//绿灯的行为
Traffic.GREEN.action();
}
}
class Student{
//性别
Sex sex ;
}
/*
class Sex {
//只有两个对象
private Sex(){}
private static Sex in = new Sex();
private static Sex in1 = new Sex();
}*/
enum Sex{
MALE,FEMALE;//表示该类的对象,必须放在枚举类的第一行,直接写枚举类对象的名称,由于是static final一般全部大写。
int a;//属性
public void fun(){
System.out.println("这是Sex中的方法。。。");
}
}
//enum
enum Traffic{
RED{
@Override
public void action() {
System.out.println("红灯停");
}
} ,YELLOW {
@Override
public void action() {
System.out.println("黄灯等待");
}
},GREEN{
@Override
public void action() {
System.out.println("绿灯行");
}
};
public abstract void action();
}
//四季
enum Season{
SPRING("春季"),SUMMER("夏季"), AUTUMN("秋季"),WINTER("冬季");
private String desc;
//构造方法注入
private Season(String desc){
this.desc = desc;
}
// private Season(){}
}
线程的生命周期
java中Thread类提供了6个状态
概念
Thread.State
NEW
至今尚未启动的线程处于这种状态。
RUNNABLE
正在 Java 虚拟机中执行的线程处于这种状态。
BLOCKED
受阻塞并等待某个监视器锁的线程处于这种状态。
WAITING
无限期地等待另一个线程来执行某一特定操作的线程处于这种状态。
TIMED_WAITING
等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。
TERMINATED
已退出的线程处于这种状态。
线程池
概念
线程池:是用来管理线程的"池子".频繁的创建和销毁的线程,会增大内存的消耗,为了降低内存的消耗,使用线程池来管理和循环利用线程。
java中提供的线程池
Executor 管理线程的接口
子接口:
ExecutorService
常用方法:
① submit(Runnable task) 提交线程
② shutdown() 执行之前提交的任务,并且关闭线程池
Executors:线程池的工厂类。
常用方法:
① newCachedThreadPool() 创建一个可根据需要创建新线程的线程池,池中的线程不够,就创
建。会导致线程过多,造成内存泄漏。
② newFixedThreadPool(int nThreads) 创建一个可重用固定线程数的线程池,线程池中线
程是固定的,如果任务数大于线程数,等待。如果线程任务执行长,等待时间就会过长。
代码
package com.demo;
import java.util.concurrent.*;
/**
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory, RejectedExecutionHandler handler)
参数:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任 务。
ArrayBlockingQueue:由数组支持的有界任务队列。 ArrayBlockingQueue(int capacity)
threadFactory - 执行程序创建新线程时使用的工厂。 Executors.defaultThreadFactory()
handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。
在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序遭到拒绝将抛出运行时 RejectedExecutionException。
在 ThreadPoolExecutor.CallerRunsPolicy 中,线程调用运行该任务的 execute 本 身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
在 ThreadPoolExecutor.DiscardPolicy 中,新的不能执行的任务将被删除。
在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行程序尚未关闭,则位于 工作队列头部的任务将被删除,
然后重试执行程序(如果再次失败,则重复此过程)。
*/
public class ThreadPoolExecutor线程池 {
public static void main(String[] args) {
ThreadPoolExecutor tp = new ThreadPoolExecutor(3, 5, 1,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
for (int i = 0; i < 7; i++) {
int finalI = i;//1.8jdk之后,在内部类中使用时,加final或省略都是加的。
tp.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"======>"+ finalI);
}
});
}
}
}
ThreadPoolExecutor
1.引入 ThreadPoolExecutor:可以解决线程的管理问题,由于newCachedThreadPool()在使用时,可能会
造成线程的过多,
newFixedThreadPool(int nThreads)创建的线程池,可能会造成等待时间过长,为了平衡这两种现
象,引入了
ThreadPoolExecutor。
2.创建对象
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue
ThreadFactory threadFactory, RejectedExecutionHandler handler)
参数:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任
务。
ArrayBlockingQueue:由数组支持的有界任务队列。 ArrayBlockingQueue(int
capacity)
threadFactory - 执行程序创建新线程时使用的工厂。 Executors.defaultThreadFactory()
handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。
在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序遭到拒绝将抛出运行时
RejectedExecutionException。
在 ThreadPoolExecutor.CallerRunsPolicy 中,线程调用运行该任务的 execute 本 身。此策
略提供简单的反馈控制机制,能够减缓新任务的提交速度。
在 ThreadPoolExecutor.DiscardPolicy 中,新的不能执行的任务将被删除。
在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行程序尚未关闭,则位于 工作队列
头部的任务将被删除,
然后重试执行程序(如果再次失败,则重复此过程)。
package com.demo;
import java.util.concurrent.*;
/**
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory, RejectedExecutionHandler handler)
参数:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任
务。
ArrayBlockingQueue:由数组支持的有界任务队列。 ArrayBlockingQueue(int
capacity)
threadFactory - 执行程序创建新线程时使用的工厂。 Executors.defaultThreadFactory()
handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。
在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序遭到拒绝将抛出运行时
RejectedExecutionException。
在 ThreadPoolExecutor.CallerRunsPolicy 中,线程调用运行该任务的 execute 本 身。此策
略提供简单的反馈控制机制,能够减缓新任务的提交速度。
在 ThreadPoolExecutor.DiscardPolicy 中,新的不能执行的任务将被删除。
在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行程序尚未关闭,则位于 工作队列
头部的任务将被删除,
然后重试执行程序(如果再次失败,则重复此过程)。
*/
public class ThreadPoolExecutor线程池 {
public static void main(String[] args) {
ThreadPoolExecutor tp = new ThreadPoolExecutor(3, 5, 1,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(1),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
for (int i = 0; i < 7; i++) {
int finalI = i;//1.8jdk之后,在内部类中使用时,加final或省略都是加的。
tp.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"======>"+ finalI);
}
});
}
}
}