多线程..

线程定义:线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中实际运作单位。简单来说,应用软件中相互独立,可以同时运作的功能。

多线程作用:有了多线程,我们就可以让程序同时做多件事情。

应用场景:只要你想让多个事件同时运行就需要用到多线程。

并发:在同一时刻,有多个指令在单个CPU上交替执行。

并行:在同一时刻,有多个指令在多个CPU上同时执行。

多线程的实现方式

1.继承Thread类的方式进行执行

步骤:

自己定义一个类继承Thread

重写run方法

创建子类的对象,并启动线程。

public class MyThread extends Thread{
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println("Hello");
		}
	}

}
public class test {
    public static void main(String [] args)  {
    	//创建子类对象,开启线程
    	MyThread mt=new MyThread();
    	mt.start();
	 }
}

2.实现Runnable接口的方式进行实现

步骤:

自己定义一个类实现Runnable接口

重写里面的run方法

创建自己类的对象

创建一个Thread类的对象,并开启线程。

public class MyThread implements Runnable{
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println("world");
		}
	}

}
public class test {
    public static void main(String [] args)  {
    	//创建自己类的对象
    	MyThread mt=new MyThread();
    	//创建Thread对象,并开启线程
    	Thread t=new Thread(mt);
    	t.start();
	 }
}

 

若想看看两个线程的相互执行,获取线程的名字:

public class MyThread implements Runnable{
	//在此获取线程的名字
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
		Thread t=Thread.currentThread();//获取当前线程对象
		System.out.println(t.getName()+":world");
		}
	}

}
public class test {
    public static void main(String [] args)  {
    	//创建自己类的对象
    	MyThread mt=new MyThread();
    	//创建Thread对象,并开启线程
    	Thread t1=new Thread(mt);
    	Thread t2=new Thread(mt);
    	//给线程设置名字
    	t1.setName("线程1");
    	t2.setName("线程2");
    	t1.start();
    	t2.start();
	 }
}

3.利用Callable接口和Future接口方式实现

特点:可以获取多线程运行的结果。

1)创建一个MyCallable类实现Callable接口;

2)重写call方法(是有返回值的,表示多线程运行的结果);

3)创建MyCallable的对象(表示多线程要执行的任务);

4)创建FutureTask的对象(作用管理多线程的运行结果);

5)创建Thread类的对象,并启动(表示线程)。

public class MyCallable implements Callable<Integer>{
    //计算1~10的和
	@Override
	public Integer call() throws Exception {
		int sum=0;
		for(int i=0;i<=10;i++) {
			sum+=i;
		}
		return sum;
	}

}
public class test {
    public static void main(String [] args) throws InterruptedException, ExecutionException  {
    	MyCallable mc=new MyCallable();
    	FutureTask<Integer> ft=new FutureTask<>(mc);//管理多线程运行结果
    	Thread t=new Thread(ft);
    	t.start();//开启线程
    	//获取返回值
         Integer sum=ft.get();
         System.out.println(sum);
	 }
}

多线程的成员方法

获取与设置线程的名字

注:若我们未给线程设置名字,线程也有默认的名字,格式:Thread-X(X为序号,从0开始)。

若我们要给线程设置名字,可以用set方法,也可以用构造方法(调用父类的构造方法)设置。

1)用set进行设置。

public class MyThread extends Thread{
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			//获取线程名字
			System.out.println(getName()+":"+i);
		}
	}

}

public class test {
    public static void main(String [] args)  {
    	MyThread t1=new MyThread();
    	MyThread t2=new MyThread();
    	//设置线程名字,用set方法设置
    	t1.setName("线程1");
    	t2.setName("线程2");
    	t1.start();
    	t2.start();
	 }
}

线程之间交替运行。 

2)用构造方法进行设置

public class MyThread extends Thread{
	public MyThread() {//调用父类的构造方法
		
	}
	public MyThread(String name) {
		super(name);
	}
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println(getName()+":"+i);
		}
	}

}
public class test {
    public static void main(String [] args)  {
    	MyThread t1=new MyThread("飞机");
    	MyThread t2=new MyThread("鼠标");
    	t1.start();
    	t2.start();
	 }
}

线程休眠

static void sleep(long time)——让线程休眠指定时间,单位毫秒。

注:哪条线程执行到这个方法,那么哪条线程就会在这停留对应的时间。当时间到了之后,线程会自动醒来,执行下面的代码。

public class MyThread extends Thread{
	public MyThread() {//调用父类的构造方法
		
	}
	public MyThread(String name) {
		super(name);
	}
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			try {
				Thread.sleep(1000);//每个一秒打印一个数据
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(getName()+":"+i);
		}
	}

}
public class test {
    public static void main(String [] args)  {
    	MyThread t1=new MyThread("飞机");
    	MyThread t2=new MyThread("鼠标");
    	t1.start();
    	t2.start();
	 }
}

线程的优先级

在java中使用抢占式调度,其特点为随机性。优先级为1~10,默认优先级为5,优先级越高,抢到CPU的概率越大,但并不是百分之一百抢到CPU。

public class MyThread extends Thread{
	@Override
	public void run() {
		for(int i=0;i<7;i++) {
			System.out.println(getName()+":"+i);
		}
	}
}
public class test {
    public static void main(String [] args)  {
    	MyThread t1=new MyThread();
    	MyThread t2=new MyThread();
    	//设置线程名字
    	t1.setName("键盘");
    	t2.setName("鼠标");
    	//设置线程的优先级
    	t1.setPriority(1);
    	t2.setPriority(10);
    	t1.start();
    	t2.start();
	 }
}

鼠标优先级大,鼠标先执行完毕。

守护线程

当其他非守护线程结束后,守护线程也会陆续结束(一般不会执行完毕)。

public class MyThread1 extends Thread{
	@Override
	public void run() {
		for(int i=0;i<8;i++) {
			System.out.println(getName()+":"+i);
		}
	}
}
public class MyThread2 extends Thread{
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println(getName()+":"+i);
		}
	}
}
public class test {
    public static void main(String [] args)  {
    	MyThread1 t1=new MyThread1();
    	MyThread2 t2=new MyThread2();
    	//设置线程名字
    	t1.setName("线程");
    	t2.setName("备份");
    	//将t2设置为守护线程
    	t2.setDaemon(true);
    	t1.start();
    	t2.start();
	 }
}

礼让线程

礼让线程也叫出让线程,作用:尽可能使结果均匀一点。

public class MyThread extends Thread{
	@Override
	public void run() {
		for(int i=0;i<8;i++) {
			System.out.println(getName()+":"+i);
			Thread.yield();//出让线程
		}
	}
}
public class test {
    public static void main(String [] args)  {
    	MyThread t1=new MyThread();
    	MyThread t2=new MyThread();
    	//设置线程名字
    	t1.setName("线程1");
    	t2.setName("线程2");
    	
    	t1.start();
    	t2.start();
	 }
}

插入线程

public class MyThread extends Thread{
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println(getName()+":"+i);
		}
	}
}
public class test {
    public static void main(String [] args) throws InterruptedException  {
    	MyThread t1=new MyThread();	
    	t1.setName("土豆");
    	t1.start();
    	t1.join();//插入线程,将土豆线程插入到main线程之前
    	for(int i=0;i<10;i++) {
    		System.out.println("main线程"+i);
    	}
	 }
}

线程的生命周期

同步代码块

把操作共享的代码锁起来。

锁对象一定要求是唯一的。

 利用同步代码块可解决线程安全问题。若没有锁,可能会出现数据重复,数据超出要求的范围等等问题。

练习

某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票。

public class MyThread extends Thread{
	//设置一个静态数据,表示这个类所有对象可以共享
	  static int ticket=0;//票数
	  static Object obj=new Object();//锁对象一定要是唯一的
	@Override
	public void run() {
		while(true) {
			synchronized(obj) {
			if(ticket<100) {
				try {
					Thread.sleep(100);//数据慢慢的输出
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				ticket++;
				System.out.println(getName()+"今天卖出第"+ticket+"票");
			}else {
				break;
			}
			}
		}
	}
}
public class test {
    public static void main(String [] args)  {
    	MyThread t1=new MyThread();
    	MyThread t2=new MyThread();
    	MyThread t3=new MyThread();
    	//设置名字
    	t1.setName("窗口1");
    	t2.setName("窗口2");
    	t3.setName("窗口3");
    	t1.start();
    	t2.start();
    	t3.start();
	 }
}

同步方法

就是把synchronized关键字加到方法上。

同步方法是用同步代码块提取方法,改编而来的。

练习

某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票。(使用同步方法完成,技巧:先构建好同步代码块,在进行变换)

public class MyThread implements Runnable{//使用第二种方法
    int ticket=0;//使用第二种方法创建对象,不用设置这个为静态的
    @Override
    public void run() {
        while(true) {       
                if (mehod()) break;         
        }

    }
    private synchronized boolean mehod() {//同步方法
        if(ticket==100) {
            return true;
        }else {
            try {
                Thread.sleep(100);//若想要看到多个线程交织进行,可采用sleep让线程睡一会
            } catch (final InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            ticket++;
            System.out.println(Thread.currentThread().getName()+"今天卖了第"+ticket+"张票");
        }
        return false;
    }


}
public class test1 {
    public static void main(String[] args) {
        MyThread mt=new MyThread();
        Thread t1=new Thread(mt);
        Thread t2=new Thread(mt);
        Thread t3=new Thread(mt);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

Lock锁


 练习

某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票。(利用Lock锁进行)

在Lock锁当中利用try-catch-finall来进行开锁关锁。,将while循环中的主体程序写完之后,从获得锁开始后利用快捷方法生成try-catch-finall,finally中写释放锁。

public class MyThread extends Thread{
    //设置一个静态数据,表示这个类所有对象可以共享
    static int ticket=0;
    Lock lock=new ReentrantLock();//创建一个锁对象
    @Override
    public void run() {
        while(true) {
          //  synchronized (MyThread.class) {
            lock.lock();//获得锁
            try {
                if (ticket < 100) {
                        Thread.sleep(100);//数据慢慢的输出
                    ticket++;
                    System.out.println(getName() + "今天卖出第" + ticket + "票");
                } else {
                    break;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();//释放锁
            }
            // }
        }
    }
}
public class test1 {
    public static void main(String[] args) {
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        MyThread t3=new MyThread();
        //设置名字
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
    }

书写进程步骤:

生产者和消费者(等待唤醒机制)

生产者消费者模式是一个十分经典的多线程协作的模式。

例如:吃货和厨师(消费者和生产者)

常见方法:

实现方法1:基本方法 

 有:生产者、消费者、控制生产者和消费者的代码

先写中间:

public class Desk {//中间变量
    //作用:控制消费者和生产者的代码
    //定义桌子状态,0无面条,1有面条
    public static int state=0;
    //定义吃货最大能吃多少,总个数
    public static int count=10;
    //定义锁对象
    public static Object lock=new Object();
}

消费者:

public class Eat extends Thread{//消费者
    //循环
    //同步代码块(同步方法,锁方法均可)
    //判断共享数据是否到末尾(先写到了末尾,再写未到末尾)
    @Override
    public void run(){
        while(true){
            synchronized (Desk.lock){//锁对象
                //判断共享数据是否到末尾
                if(Desk.count==0){
                    break;
                }else{
                    //先判断桌子上物品状态
                    if(Desk.state==0){
                        //如果没有消费者等待
                        try {
                            Desk.lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }else{
                        //如果有
                        Desk.count--;
                        System.out.println("这个人还能再吃"+Desk.count+"碗饭");
                        //吃完唤醒厨师继续做
                        Desk.lock.notifyAll();
                        //修改桌子状态
                        Desk.state=0;
                    }

                }
            }
        }
    }
}

生产者:

public class Cook extends Thread{//生产者
    @Override
    public void run(){
        while(true){
            synchronized (Desk.lock){
                if(Desk.count==0){
                    break;
                }else{
                    //判断桌子状态
                    if(Desk.state==1){
                        //如果有,就等待
                        try {
                            Desk.lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }else{
                        //如果没有
                        System.out.println("厨师做了一碗面");
                        //修改桌子状态
                        Desk.state=1;
                        //唤醒消费者
                        Desk.lock.notifyAll();
                    }
                }
            }
        }
    }
}

测试类:

public class test1 {
    public static void main(String[] args) {
        Cook c=new Cook();
        Eat e=new Eat();
        //设置名字
        c.setName("厨师:");
        e.setName("吃货");
        //开启线程
        c.start();
        e.start();
    }
    }

实现方法2:阻塞队列方法实现

 阻塞队列的接口和实现类:

public class Cook extends Thread{//生产者
    ArrayBlockingQueue<String> queue;

    public Cook(ArrayBlockingQueue<String> queue) {
        this.queue=queue;
    }

    @Override
    public void run(){
        while(true){
            //调用阻塞队列将面条放入
            try {
                queue.put("面条");
                System.out.println("厨师放了一碗面条");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class Eat extends Thread{//消费者
    ArrayBlockingQueue<String> queue;

    public Eat(ArrayBlockingQueue<String> queue) {
        this.queue=queue;
    }

    @Override
    public void run(){
        while(true){
            try {
                String food=queue.take();
                System.out.println(food);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }


        }
    }
}
public class test1 {
    public static void main(String[] args) {
      //创建阻塞队列
        ArrayBlockingQueue<String> queue=new ArrayBlockingQueue<>(10);//定义阻塞队列中的队列长度
        Cook c=new Cook(queue);
        Eat e=new Eat(queue);
        c.setName("厨师");
        e.setName("吃货");
        c.start();
        e.start();
    }
    }

线程的六种状态

综合练习

练习1:抢红包

(因为获取Double类型的随机数只能在JDK17中,抢红包实际抢到的是小数,在此题下理想化,认为是整数)
抢红包也用到了多线程。假设: 100块,分成了3个包,现在有5个人去抢。其中,红包是共享数据。5个人是5条线程。
打印结果如下:
XXX抢到了XXX元
XXX抢到了XXX元
XXX抢到了XXX元
XXX没抢到
XXX没抢到

package test1;
import java.util.Random;
public class MyThread extends  Thread{
    //定义静态变量
    static  int money=100;//总金额
    static int count=3;//红包个数
    static final int MIN=1;//抢到的金额的最小值
    @Override
    public void run() {
        synchronized (MyThread.class) {
            //判断金额
            if (money == 0) {
                System.out.println(getName() + "没有抢到红包");
            } else {
                //判断红包个数
                int prize = 0;//中奖金额
                if (count == 1) {
                    //只剩一个红包,中奖金额就是余额
                    prize = money;
                } else {
                    //进行随机数,获取红包金额
                    Random r = new Random();
                    int bound = money - (count - 1) * MIN;
                    prize = r.nextInt(bound);
                    if (prize < MIN) {
                        prize = MIN;
                    }
                }
                money = money - prize;
                count--;
                System.out.println(getName() + "抢到了" + prize + "元");
            }
        }
    }
}
public class test1 {
    public static void main(String[] args) {
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        MyThread t3=new MyThread();
        MyThread t4=new MyThread();
        MyThread t5=new MyThread();
        t1.setName("张三");
        t2.setName("李四");
        t3.setName("王五");
        t4.setName("赵六");
        t5.setName("导航");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
    }

练习2:抽奖池抽奖

有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为{10,5,20,50,100,200,500,800,2,80,300,700};
创建两个抽奖箱(线程)设置线程名称分别为“ 抽奖箱1”,‘ '抽奖箱2”随机从抽奖池中获取奖项元素并打印在控制台上格式如下:
每次抽出一个奖项就打印一个(随机)
抽奖箱1又产生了一个10元大奖
抽奖箱1又产生了一个100元大奖
抽奖箱2又产生了一个700元大奖
分析:可用集合和数组进行,但数组去重比较复杂,利用集合完成。

public class MyThread extends  Thread {
    ArrayList<Integer> list;//静态变量

    //可以利用构造方法
    public MyThread(ArrayList<Integer> list) {
        this.list = list;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (MyThread.class) {
                if (list.size() == 0) {
                    break;
                } else {
                    Collections.shuffle(list);//打乱list数据
                    int prize = list.remove(0);
                    System.out.println(getName() + "又产生了一个" + prize + "大奖");
                }
            }
            try {
                Thread.sleep(100);//目的是可以让两个线程交替进行显示
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }
    }
}
public class test1 {
    public static void main(String[] args) {
        ArrayList<Integer> list=new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,200,500,800,2,80,300,700);
        MyThread t1=new MyThread(list);
        MyThread t2=new MyThread(list);
        t1.setName("抽奖箱1");
        t2.setName("抽奖箱2");
        t1.start();
        t2.start();
    }
    }

练习3:多线程统计并求最大值

在上一题基础上继续完成如下需求:
每次抽的过程中,不打印,抽完时一次性打印(随机),在此次抽奖过程中,抽奖箱1总共产生了6个奖项。
分别为: 10,20,100,500,2,300最高奖项为300元,总计额为932元在此次抽奖过程中,抽奖箱2总共产生了6个奖项。
分别为: 5, 50,200,800,80,700最高奖项为800元,总计额为1835元

解法一:对第一个程序进行改编
 

public class MyThread extends  Thread{
    ArrayList<Integer> list;//静态变量
    //可以利用构造方法
    public MyThread(ArrayList<Integer> list){
        this.list=list;
    }
    //创建两个集合来存放数据
    static  ArrayList<Integer> list1=new ArrayList<>();
   static ArrayList<Integer> list2=new ArrayList<>();
    @Override
    public void run(){
        while(true){
          synchronized (MyThread.class) {
            if(list.size()==0){
                if("抽奖箱1".equals(getName())){
                    System.out.println("抽奖箱1"+list1);
                    int max=0;
                    int count=0;
                    for(int i=0;i<list1.size();i++){
                        if(max<= list1.get(i)){
                            max=list1.get(i);
                        }
                        count+=list1.get(i);
                    }
                    System.out.println("抽奖箱1最大奖"+max);
                    System.out.println("抽奖箱1总计"+count);
                }else if("抽奖箱2".equals(getName())) {
                    System.out.println("抽奖箱2"+list2);
                    int max=0;
                    int count=0;
                    for(int i=0;i<list2.size();i++){
                        if(max<= list2.get(i)){
                            max=list2.get(i);
                        }
                        count+=list2.get(i);
                    }
                    System.out.println("抽奖箱2最大奖"+max);
                    System.out.println("抽奖箱2总计"+count);
                }
                break;
            }else{
                Collections.shuffle(list);//打乱list数据
                int prize=list.remove(0);
               //进行判断
                if("抽奖箱1".equals(getName())){
                    list1.add(prize);
                }else if("抽奖箱2".equals(getName())){
                    list2.add(prize);
                }
            }
        }
}
        try {
            Thread.sleep(10);//目的是可以让两个线程交替进行显示
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

}

解法二:线程栈

public class MyThread extends  Thread {
    ArrayList<Integer> list;//静态变量

    //可以利用构造方法
    public MyThread(ArrayList<Integer> list) {
        this.list = list;
    }

    @Override
    public void run() {
        ArrayList<Integer> List=new ArrayList<>();
        while (true) {
            synchronized (MyThread.class) {
                if (list.size() == 0) {
                    System.out.println(getName()+List);
                    break;
                } else {
                    Collections.shuffle(list);//打乱list数据
                    int prize = list.remove(0);
                    List.add(prize);
                }
            }
            try {
                Thread.sleep(100);//目的是可以让两个线程交替进行显示
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }
    }
}

练习4:多线程之间的比较

在上一题基础上继续完成如下需求:在此次抽奖过程中,抽奖箱1总共产生了6个奖项,分别为: 10,20,100,500,2,300,最高奖项为300元,总计额为932元
在此次抽奖过程中,抽奖箱2总共产生了6个奖项,分别为: 5,50,200,800,80,700
最高奖项为800元,总计额为1835元
在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为800元
分析:最大奖项应该这两个线程结束后再比较,采用有返回值的线程创建方法,将最大值返回后打印。

public class MyCallable implements Callable<Integer> {
    ArrayList<Integer> list;//静态变量

    //可以利用构造方法
    public MyCallable(ArrayList<Integer> list) {
        this.list = list;
    }

    @Override
    public Integer call() throws Exception {
        ArrayList<Integer> List=new ArrayList<>();
        while (true) {
            synchronized (MyCallable.class) {
                if (list.size() == 0) {
                    System.out.println(Thread.currentThread().getName()+List);
                    break;
                } else {
                    Collections.shuffle(list);//打乱list数据
                    int prize = list.remove(0);
                    List.add(prize);
                }
            }
                Thread.sleep(100);//目的是可以让两个线程交替进行显示
        }
        //把集合中的最大值返回
        if(List.size()==0){
            return null;
        }else{
           return Collections.max(List);
        }

    }
}
public class test1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ArrayList<Integer> list=new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,200,500,800,2,80,300,700);
        MyCallable mc=new MyCallable(list);
        FutureTask<Integer> ft1=new FutureTask<>(mc);
        FutureTask<Integer> ft2=new FutureTask<>(mc);
        Thread t1=new Thread(ft1);
        Thread t2=new Thread(ft2);
        t1.setName("抽奖箱1");
        t2.setName("抽奖箱2");
        t1.start();
        t2.start();
        int max1=ft1.get();
        int max2=ft2.get();
        System.out.println(max1);
        System.out.println(max2);
    }
    }

线程池

核心原理:

创建线程池

创建一个没有上限的线程池:

public class MyRunnable implements Runnable{

    @Override
    public void run() {
        for(int i=1;i<=100;i++){
            System.out.println(Thread.currentThread().getName()+"--"+i);
        }
    }
}
public class test1 {
    public static void main(String[] args)  {
        //创建线程池对象
      ExecutorService poll= Executors.newCachedThreadPool();
      //提交任务
        poll.submit(new MyRunnable());
        poll.submit(new MyRunnable());
        poll.submit(new MyRunnable());
        //线程池一般不会关闭
    }
    }

 

创建一个有上限的线程池:

public class test1 {
    public static void main(String[] args)  {
        //创建线程池对象
      ExecutorService poll= Executors.newFixedThreadPool(2);
      //提交任务
        poll.submit(new MyRunnable());
        poll.submit(new MyRunnable());
        poll.submit(new MyRunnable());
        //线程池一般不会关闭
    }
    }

自定义线程池

系统先会创建服务于任务1、2、3的线程1、2、3;再将任务4、5、6拿去排队; 再调用临时线程服务于任务7、8、9;任务10会触发任务拒绝策略。

任务拒绝策略

创建自定义线程池:

public class test1 {
    public static void main(String[] args)  {
        //自定义线程池
        ThreadPoolExecutor pool=new ThreadPoolExecutor(
                3,//核心线程的数量
                6,//最大线程数
                60,//空闲线程最大存活时间
                TimeUnit.SECONDS,//时间单位
                new ArrayBlockingQueue<>(3),//任务队列,相当于阻塞队列
                Executors.defaultThreadFactory(),//创建线程工厂:线程池如何获取到一个线程
                new ThreadPoolExecutor.AbortPolicy()//任务拒绝策略
        );
    }
    }

线程池多大合适

 

 

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值