2021-11-04  2021-11-04    7768 字   16 分钟

多线程

概念

三个概念:

① 程序:软件。数据与指令的集合。

② 进程:正在执行的程序。

③ 线程:进程中的多条执行路径。

两个概念:

① 并发:在某一个时间段内,都有执行。

② 并行:在同一时刻,同时执行。

多线程的好处:

提高了程序的执行效率。

线程也不能无限开启,必须要有度。

创建线程的方式

① 继承 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 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 中,如果执行程序尚未关闭,则位于 工作队列

头部的任务将被删除,

然后重试执行程序(如果再次失败,则重复此过程)。

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);

}

});

}

}

}

avatar
青山
悟已往之不谏 知来者之可追
一言
今日诗词
站点信息
本站访客数 :
本站总访问量 :