文章目录

  • java多线程
    • 1、线程简介
    • 2、线程实现(三种)
      • 继承Thread类(重点)
        • 步骤:
        • 示例代码:
        • 多线程下载图片:
      • 实现Runnable接口(重点)
        • 步骤:
        • 基础代码:
        • 体现Runnable的多继承性:
        • 龟兔赛跑:
      • 实现callable接口(了解)
        • 步骤:
        • 示例代码:
      • 补充:静态代理模式
        • lambda表达式
    • 3、线程状态
      • (线程五大状态)图解:
        • 1、精简:
        • 2、详细:
      • 线程方法:
        • 停止线程:
          • 停止线程推荐方式代码:
        • 线程休眠:(Thread.sleep(1000))
          • 使用案例(倒计时、打印系统当前时间)
        • 线程礼让:(Thread.yield())
        • 线程强制执行:(thread.join())
        • 线程状态:Thread.getState()
        • 线程优先级:
      • 守护线程
    • 4、线程同步
      • 简介:
      • 同步方法:
      • 同步块
        • 代码示例:
      • 死锁问题:
        • 产生死锁的四个必要条件:
      • Lock
        • 基本格式:
        • 代码示例:
    • 5、线程协作(生产消费模型)
      • 1、管程法
        • 参考代码:(引用)
      • 2、信号灯法
        • 示例代码:
      • 3、线程池(浅析,重点见下一章)
        • 分类:
        • 示例代码:

java多线程

1、线程简介

普通方法和多线程:

进程:在操作系统中运行的程序就是进程,比如你的QQ,播放器,游戏,IDE等等。

程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。

进程则是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位通常在一个进程中可以包含若干个线程,当然一

个进程中至少有一个线程,不然没有存在的意义。

线程是CPU调度和执行的的单位。

tips:

1、线程就是独立的执行路径;

2、在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;

3、main()称之为主线程,为系统的入口,用于执行整个程序;

4、在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的

千预的。

5、对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;线程会带来额外的开销,如cpu调度时间,并发控制开销。

6、每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。

2、线程实现(三种)

继承Thread类(重点)

步骤:

1、自定义线程类继承Thread类重写run()方法

2、编写线程执行体创建线程对象

3、调用start()方法启动线程

示例代码:

package Multithread;public class TestThread1 extends Thread {@Overridepublic void run() {for (int i = 0; i < 200; i++) {System.out.println("线程1");}}public static void main(String[] args) {//        两个线程同时执行new TestThread1().start();for (int i = 0; i < 200; i++) {System.out.println("主线程");}}
}

多线程下载图片:

package Multithread;import org.apache.commons.io.FileUtils;import java.io.File;
import java.io.IOException;
import java.net.URL;public class TestThread2 extends Thread {private String url;private String name;public TestThread2(String url, String name) {this.url = url;this.name = name;}@Overridepublic void run() {new Downloader().downloader(url,name);System.out.println("下载了图片:"+name);}public static void main(String[] args) {TestThread2 t1=new TestThread2("https://img-home.csdnimg.cn/images/20220928102134.jpg","1.jpg");TestThread2 t2=new TestThread2("https://img-operation.csdnimg.cn/csdn/silkroad/img/1664246005001.jpg","2.jpg");TestThread2 t3=new TestThread2("https://img-operation.csdnimg.cn/csdn/silkroad/img/1663729624980.jpg","3.jpg");t1.start();t2.start();t3.start();}
}
class Downloader{public void downloader(String url,String name){try {FileUtils.copyURLToFile(new URL(url),new File(name));} catch (IOException e) {e.printStackTrace();System.out.println("Downloader捕获到异常");}}
}

实现Runnable接口(重点)

步骤:

1、定义MyRunnable类实现Runnable接口

2、实现run()方法,编写线程执行体

3、创建线程对象,调用start()方法启动线程

基础代码:

package Multithread;public class TestThread3 implements Runnable {@Overridepublic void run() {for (int i = 0; i < 20; i++) {System.out.println("线程1");}}public static void main(String[] args) {Thread t=new Thread(new TestThread3());t.start();for (int i = 0; i < 20; i++) {System.out.println("主线程");}}
}

体现Runnable的多继承性:

package Multithread;public class TestThread4 implements Runnable{int ticket=100;@Overridepublic void run() {while (ticket>0){System.out.println(Thread.currentThread().getName()+"抢到票:"+ticket--);}}public static void main(String[] args) {TestThread4 r=new TestThread4();
//        多继承使用new Thread(r,"小明").start();//小明作为线程名new Thread(r,"李华").start();new Thread(r,"黄牛").start();}
}

龟兔赛跑:

package Multithread;public class TestRace implements Runnable{private static String winner;@Overridepublic void run() {for (int i = 0; i <=100; i++) {//            判断比赛是否结束if (gameover(i)) {break;}
//            模拟兔子睡觉if (Thread.currentThread().getName().equals("兔子")&&i%10==0){try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");}}
//    判断获胜者public Boolean gameover(int step){if (winner!=null)return true;else {if (step>=100){winner=Thread.currentThread().getName();System.out.println("获胜者是"+winner);return true;}}return false;}public static void main(String[] args) {TestRace r=new TestRace();new Thread(r,"乌龟").start();new Thread(r,"兔子").start();}
}

实现callable接口(了解)

步骤:

1、实现Callable接口,需要返回值类型

2、重写call方法,需要抛出异常

3、创建目标对象

4、创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);

5、提交执行:Future result1 = ser.submit(t1);

6、获取结果:boolean r1 = result1.get()

7、关闭服务:ser.shutdownNow();

示例代码:

package Multithread;import java.util.concurrent.*;public class TestThread5 implements Callable<Boolean> {private String url;private String name;public TestThread5(String url, String name) {this.url = url;this.name = name;}@Overridepublic Boolean call() {new Downloader().downloader(url, name);System.out.println("下载了图片:" + name);return true;}public static void main(String[] args) throws ExecutionException, InterruptedException {TestThread5 t1 = new TestThread5("https://img-home.csdnimg.cn/images/20220928102134.jpg", "1.jpg");TestThread5 t2 = new TestThread5("https://img-operation.csdnimg.cn/csdn/silkroad/img/1664246005001.jpg", "2.jpg");TestThread5 t3 = new TestThread5("https://img-operation.csdnimg.cn/csdn/silkroad/img/1663729624980.jpg", "3.jpg");//创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);ExecutorService ser = Executors.newFixedThreadPool(3);//提交执行:Future<Boolean> result1 = ser.submit(t1);Future<Boolean> r1 = ser.submit(t1);Future<Boolean> r2 = ser.submit(t2);Future<Boolean> r3 = ser.submit(t3);//获取结果:boolean r1 = result1.get()boolean rs1 = r1.get();boolean rs2 = r2.get();boolean rs3 = r3.get();//关闭服务:ser.shutdownNow();ser.shutdownNow();}
}

补充:静态代理模式

真实对象专注做自己的事情,代理对象做真实对象的附加业务。

代码:

package Multithread;
/*
* 静态代理模式
* */
//实际类和代理类需实现同一接口
public class StaticP {public static void main(String[] args) {You y=new You();wedCompany wd=new wedCompany(y);wd.happymarry();}
}
interface Marry{void happymarry();
}
//需求者
class You implements Marry{@Overridepublic void happymarry() {System.out.println("你结婚了");}
}
//代理
class wedCompany implements Marry{private Marry target;public wedCompany(Marry target) {this.target = target;}@Overridepublic void happymarry() {before();target.happymarry();after();}public void before(){System.out.println("结婚前");}public void after(){System.out.println("结婚后");}
}

lambda表达式

package Multithread;public class TestT {public static void main(String[] args) {new Thread(()-> System.out.println("哈哈哈")).start();}
}

3、线程状态

(线程五大状态)图解:

1、精简:

2、详细:

线程方法:

停止线程:

1、不推荐使用JDK提供的stop()、destroy()方法。【已废弃】

2、推荐线程自己停止下来

3、建议使用一个标志位进行终止变量当flag=false,则终止线程运行。

停止线程推荐方式代码:
package Multithread;
/*
* 推荐使用的线程停止方式,使用一个外部标志位
* */
public class StateT implements Runnable{private Boolean flag=true;@Overridepublic void run() {int i=0;while (flag){System.out.println("线程运行:"+i);}}public void stop(){this.flag=false;}public static void main(String[] args) {StateT stateT = new StateT();Thread thread = new Thread(stateT);thread.start();for (int i = 0; i < 100; i++) {System.out.println("main");if (i==90){stateT.stop();System.out.println("线程停止");}}}
}

线程休眠:(Thread.sleep(1000))

sleep(时间)指定当前线程阻塞的毫秒数;

sleep存在异常InterruptedException;

sleep时间达到后线程进入就绪状态;

sleep可以模拟网络延时,倒计时等。

每一个对象都有一个锁,sleep不会释放锁;

使用案例(倒计时、打印系统当前时间)
package Multithread;import java.text.SimpleDateFormat;
import java.util.Date;public class SleepT {public static void Down() throws InterruptedException {int times=10;while (times>=0){Thread.sleep(1000);System.out.println("倒计时:"+times--);}}public static void main(String[] args) throws InterruptedException {//        倒计时Down();
//        打印系统当前时间Date time=new Date(System.currentTimeMillis());//获取系统当前时间while (true){Thread.sleep(1000);System.out.println(new SimpleDateFormat("HH:mm:ss").format(time));time=new Date(System.currentTimeMillis());//更新系统当前时间}}
}

线程礼让:(Thread.yield())

礼让线程,让当前正在执行的线程暂停,但不阻塞

将线程从运行状态转为就绪状态

让cpu重新调度,礼让不一定成功!看CPU心情

代码:

package Multithread;public class ThreadYield {public static void main(String[] args) {mythraed mythraed = new mythraed();new Thread(mythraed,"a").start();new Thread(mythraed,"b").start();}
}
class mythraed implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"开始");Thread.yield();System.out.println(Thread.currentThread().getName()+"结束");}
}

线程强制执行:(thread.join())

Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞

可以想象成插队

测试代码:

package Multithread;public class Threadjoin implements Runnable{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("vip"+i);}}public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(new Threadjoin());thread.start();for (int i = 0; i < 200; i++) {if (i==50){thread.join();}System.out.println("主线程"+i);}}
}

线程状态:Thread.getState()

线程优先级:

Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。

线程的优先级用数字表示,范围从1~10.

Thread.MIN_PRIORITY = 1;

Thread.MAX_PRIORITY = 10;

Thread.NORM_PRIORITY = 5;(默认优先级)

使用以下方式改变或获取优先级

getPriority()

setPriority(int xxx)

测试代码:

package Multithread;public class ThreadPri implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"   "+Thread.currentThread().getPriority());}public static void main(String[] args) {ThreadPri tp=new ThreadPri();Thread t1 = new Thread(tp,"t1");Thread t2 = new Thread(tp,"t2");Thread t3 = new Thread(tp,"t3");Thread t4 = new Thread(tp,"t4");t1.setPriority(10);t2.setPriority(5);t3.setPriority(3);t4.setPriority(1);t1.start();t2.start();t3.start();t4.start();}
}

守护线程

线程分为用户线程和守护线程

虚拟机必须确保用户线程执行完毕

虚拟机不用等待守护线程执行完毕

如后台记录操作日志,监控内存,垃圾回收等待…

thread.setDaemon(true)//设置线程为守护线程

4、线程同步

简介:

形成条件:队列加锁

并发:同一个对象被多个线程操作。

线程不安全案例:

package Multithread;import java.util.ArrayList;
import java.util.List;public class Unsafe {public static void main(String[] args) {List<String > list=new ArrayList<String >();for (int i = 0; i < 10000; i++) {new Thread(()->{list.add(Thread.currentThread().getName());}).start();}System.out.println(list.size());}
}

同步方法:

由于我们可以通过private 关键字来保证数据对象只能被方法访问﹐所以我们只需要针对方法提出一套机制,这套机制就是

synchronized关键字,它包括两种用法:synchronized方法和synchronized块.

synchronized方法控制对“对象”的访问,每个对象对应一把锁

每个synchronized方法都必须获得调用该方法的对象的锁才能执行﹐否则线程会阻塞,方法一旦执行就独占该锁,直到该方

法返回才释放锁﹐后面被阻塞的线程才能获得这个锁﹐继续执行

代码:

package Multithread;public class TestThread4 implements Runnable{private int ticket=100;private Boolean flag=true;@Overridepublic void run() {while (flag){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}flag = buy();}}public synchronized Boolean buy(){if (ticket<1){return false;}System.out.println(Thread.currentThread().getName()+"抢到票:"+ticket);ticket--;return true;}public static void main(String[] args) {TestThread4 r=new TestThread4();
//        多继承使用new Thread(r,"小明").start();new Thread(r,"李华").start();new Thread(r,"黄牛").start();}
}

同步块

同步块:synchronized (Obj ){ }

Obj称之为同步监视器:

Obj可以是任何对象﹐但是推荐使用共享资源作为同步监视器。

同步方法中无需指定同步监视器﹐因为同步方法的同步监视器就是this ,就是这个对象本身,或者是class。

同步监视器的执行过程:

  1. 第一个线程访问﹐锁定同步监视器﹐执行其中代码。

2.第二个线程访问﹐发现同步监视器被锁定,无法访问。

3.第一个线程访问完毕,解锁同步监视器。

4.第二个线程访问,发现同步监视器没有锁﹐然后锁定并访问。

代码示例:

package Multithread;public class TestThread4 implements Runnable{private int ticket=100;private Boolean flag=true;@Overridepublic void run() {while (flag){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (this){flag = buy();}}}public  Boolean buy(){if (ticket<1){return false;}System.out.println(Thread.currentThread().getName()+"抢到票:"+ticket);ticket--;return true;}public static void main(String[] args) {TestThread4 r=new TestThread4();
//        多继承使用new Thread(r,"小明").start();new Thread(r,"李华").start();new Thread(r,"黄牛").start();}
}

死锁问题:

多个线程各自占有一些共享资源﹐并且互相等待其他线程占有的资源才能运行﹐而导致两个或者多个线程都在等待对方释放资

源﹐都停止执行的情形.某一个同步块同时拥有“两个以上对象的锁”时,就可能会发生“死锁”的问题。

产生死锁的四个必要条件:

1.互斥条件:一个资源每次只能被一个进程使用。

2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

3、不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

Lock

从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。

同步锁使用Lock对象充当java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。

锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象

ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。

基本格式:

代码示例:

package Multithread;import java.util.concurrent.locks.ReentrantLock;public class Lock1 {public static void main(String[] args) {TestLock testLock = new TestLock();new Thread(testLock ).start();new Thread(testLock ).start();new Thread(testLock ).start();}
}
class TestLock implements Runnable{int ticketNums=10;
//    定义Lock锁private final ReentrantLock lock=new ReentrantLock();@Overridepublic void run() {while (true){try{lock.lock();//加锁if (ticketNums>0){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(ticketNums--);}else {break;}}finally {lock.unlock();//解锁}}}
}

5、线程协作(生产消费模型)

应用场景∶生产者和消费者问题

假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费.

如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止.

如果仓库中放有产品﹐则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止.

1、管程法

参考代码:(引用)

package Multithread;public class ProAndCon1 {private static int count = 0;private static final int buffCount = 10;private static String lock = "lock";class Producer implements Runnable {@Overridepublic void run() {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock) {while (count == buffCount) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}count++;System.out.println(Thread.currentThread().getName() + "-生产者生产,数量为:" + count);lock.notifyAll();}}}}class Consumer implements Runnable {@Overridepublic void run() {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock) {while (count == 0) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}count--;System.out.println(Thread.currentThread().getName() + "-消费者消费,数量为:"+ count);lock.notifyAll();}}}}public static void main(String[] args) {ProAndCon1 waitTest = new ProAndCon1();new Thread(waitTest.new Producer()).start();new Thread(waitTest.new Consumer()).start();new Thread(waitTest.new Producer()).start();new Thread(waitTest.new Consumer()).start();new Thread(waitTest.new Producer()).start();new Thread(waitTest.new Consumer()).start();}
}

运行结果:

Thread-0-生产者生产,数量为:1
Thread-3-消费者消费,数量为:0
Thread-2-生产者生产,数量为:1
Thread-4-生产者生产,数量为:2
Thread-5-消费者消费,数量为:1
Thread-1-消费者消费,数量为:0
Thread-4-生产者生产,数量为:1
Thread-5-消费者消费,数量为:0
Thread-2-生产者生产,数量为:1
Thread-1-消费者消费,数量为:0
Thread-0-生产者生产,数量为:1
Thread-3-消费者消费,数量为:0
Thread-2-生产者生产,数量为:1
Thread-1-消费者消费,数量为:0
Thread-4-生产者生产,数量为:1
Thread-0-生产者生产,数量为:2
Thread-5-消费者消费,数量为:1
Thread-3-消费者消费,数量为:0
Thread-4-生产者生产,数量为:1
Thread-0-生产者生产,数量为:2
Thread-5-消费者消费,数量为:1
Thread-3-消费者消费,数量为:0
Thread-2-生产者生产,数量为:1
Thread-1-消费者消费,数量为:0
Thread-2-生产者生产,数量为:1
Thread-4-生产者生产,数量为:2
Thread-1-消费者消费,数量为:1
Thread-5-消费者消费,数量为:0
Thread-0-生产者生产,数量为:1
Thread-3-消费者消费,数量为:0
Thread-4-生产者生产,数量为:1
Thread-1-消费者消费,数量为:0
Thread-2-生产者生产,数量为:1
Thread-3-消费者消费,数量为:0
Thread-0-生产者生产,数量为:1
Thread-5-消费者消费,数量为:0
Thread-2-生产者生产,数量为:1
Thread-5-消费者消费,数量为:0
Thread-4-生产者生产,数量为:1
Thread-0-生产者生产,数量为:2
Thread-1-消费者消费,数量为:1
Thread-3-消费者消费,数量为:0

2、信号灯法

实质是缓冲区为1的线程池

示例代码:

package Multithread;public class PlayAndW {public static void main(String[] args) {TV tv=new TV();new Thread(new Player(tv)).start();new Thread(new Watcher(tv)).start();}
}//演员
class Player implements Runnable{TV tv;public Player(TV tv) {this.tv = tv;}@Overridepublic void run() {for (int i = 0; i < 30; i++) {if (i%2==0){this.tv.play("B站LOL直播中");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}else {this.tv.play("抖音视频");try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}}}
}
//观众
class Watcher implements Runnable{TV tv;public Watcher(TV tv) {this.tv = tv;}@Overridepublic void run() {for (int i = 0; i < 30; i++) {this.tv.watch();}}
}class TV{String voice;Boolean flag=true;
//    表演public synchronized void play(String voice){if (!flag) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("演员表演了:"+voice);this.voice=voice;this.flag=!this.flag;this.notifyAll();//通知观众观看}
//    观看public synchronized void watch(){if (flag){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("观看了节目:"+this.voice);
//        通知演员表演this.flag=!this.flag;this.notifyAll();}
}

运行结果:

演员表演了:B站LOL直播中
观看了节目:B站LOL直播中
演员表演了:抖音视频
观看了节目:抖音视频
演员表演了:B站LOL直播中
观看了节目:B站LOL直播中
演员表演了:抖音视频
观看了节目:抖音视频
演员表演了:B站LOL直播中
观看了节目:B站LOL直播中
演员表演了:抖音视频
观看了节目:抖音视频
演员表演了:B站LOL直播中
观看了节目:B站LOL直播中
演员表演了:抖音视频
观看了节目:抖音视频
演员表演了:B站LOL直播中
观看了节目:B站LOL直播中
演员表演了:抖音视频
观看了节目:抖音视频
演员表演了:B站LOL直播中
观看了节目:B站LOL直播中
演员表演了:抖音视频
观看了节目:抖音视频
演员表演了:B站LOL直播中
观看了节目:B站LOL直播中

3、线程池(浅析,重点见下一章)

背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。

思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。

好处:
提高响应速度(减少了创建新线程的时间)

​ 降低资源消耗(重复利用线程池中线程,不需要每次都创建)

​ 便于线程管理(…)

​ corePoolSize:核心池的大小

​ maximumPoolSize:最大线程数

​ keepAliveTime:线程没有任务时最多保持多长时间后会终止

JDK 5.0起提供了线程池相关API: ExecutorService和Executors

ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor

​ void execute(Runnable command)∶执行任务/命令,没有返回值,一般用来执行Runnable

​ Future submit(Callable task):执行任务,有返回值,一般又来执行Callable

​ void shutdown()∶关闭连接池

Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

分类:

FixedThreadPool:固定长度的线程池,可以控制线程的最大并发数,超出的线程会放到队列中。

SingleThreadExecutor:单线程线程池,它只会用唯一的线程来执行任务。

CachedThreadPool:可缓存的线程池,如果数据请求过多,它会不断创建新的线程,并且它还可以灵活回收空闲的线程。

ScheduledThreadPool:用于定时执行任务的线程池。

示例代码:

package Multithread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TestPool {public static void main(String[] args) {//    1、创建服务//    2、创建线程池ExecutorService service= Executors.newFixedThreadPool(10);//10线程池大小service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());service.shutdown();}
}
class MyThread implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}
}
:执行任务,有返回值,一般又来执行Callable​       void shutdown()∶关闭连接池**Executors**:工具类、线程池的工厂类,用于创建并返回不同类型的线程池#### 分类:FixedThreadPool:固定长度的线程池,可以控制线程的最大并发数,超出的线程会放到队列中。SingleThreadExecutor:单线程线程池,它只会用唯一的线程来执行任务。CachedThreadPool:可缓存的线程池,如果数据请求过多,它会不断创建新的线程,并且它还可以灵活回收空闲的线程。ScheduledThreadPool:用于定时执行任务的线程池。<img src="https://typora-cos-1313444299.cos.ap-nanjing.myqcloud.com/c7589d41259a8c1da160f1754c3c8e1f.png" alt="image-20221004164756853" style="zoom: 50%;" />#### 示例代码:```java
package Multithread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TestPool {public static void main(String[] args) {//    1、创建服务//    2、创建线程池ExecutorService service= Executors.newFixedThreadPool(10);//10线程池大小service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());service.shutdown();}
}
class MyThread implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}
}

java多线程全面解析相关推荐

  1. Java多线程技术解析

    Java多线程技术 1.多线程的概述 1.1.进程与线程 进程是操作系统进行资源分配和调度的一个独立单位,它是一个内存中运行的应用程序的载体,每个进程都有一个独立的内存空间.进程一般由程序,数据集合和 ...

  2. java resume过时方法_学点开发|关于Java多线程用法解析

    在进行学习之前,我们先来了解下,什么是Java多线程: 多线程是实现并发机制的一种有效手段.进程和线程一样,都是实现并发的一个基本单位.为了让大家更清晰读懂关于Java多线程用法,由以下几点入手学,帮 ...

  3. java多线程的安全_【JAVA多线程安全问题解析】

    一.问题的提出 以买票系统为例: 1 class Ticket implementsRunnable2{3 public int sum=10;4 public voidrun()5{6 while( ...

  4. [遇见时光]Java多线程

    原博:http://www.codeceo.com/article/java-mult-thread.html,本博文加入自己的理解.更详细参考http://blog.csdn.net/evankak ...

  5. 【2021最新版】Java多线程并发面试题总结(108道题含答案解析)

    文章目录 JAVA并发知识库 1.Java中实现多线程有几种方法? 2.继承Thread类 3.实现Runnable接口. 4.ExecutorService.Callable.Future有返回值线 ...

  6. 当初我要是这么学习Java多线程就好了「附图文解析」

    文章目录 1. 概念篇 1.1 认识进程 1.2 进程性质 1.3 操作系统如何管理进程 1.4 多线程和多进程 1.5 时间片 1.6 并发与并行 1.7 内核态与用户态 1.8 进程中的上下文 1 ...

  7. Java多线程——Thread Runnable源码解析

    Java多线程的两种实现方法大家都应该知道了:继承Thread的子类实例化和实现Runnable接口用这个接口实现类去创建Thread实例. Java的线程在Linux平台上使用的是NPTL机制,JV ...

  8. java线程内存模型_深度解析Java多线程的内存模型

    内部java内存模型 硬件层面的内存模型 Java内存模型和硬件内存模型的联系 共享对象的可见性 资源竞速 Java内存模型很好的说明了JVM是如何在内存里工作的,JVM可以理解为java执行的一个操 ...

  9. 【Java系列】深入解析Java多线程

    序言 你只管努力,其他交给时间,时间会证明一切. 文章标记颜色说明: 黄色:重要标题 红色:用来标记结论 绿色:用来标记一级重要 蓝色:用来标记二级重要 希望这篇文章能让你不仅有一定的收获,而且可以愉 ...

最新文章

  1. TVM将深度学习模型编译为WebGL
  2. 捣鼓 Subversion
  3. leetcode算法题--回文链表
  4. MySQL数据库是非关系_MySQL(数据库)基础知识、关系型数据库yu非关系型数据库、连接认证...
  5. idea yml变成文件了_初识SpringBoot之配置文件(二)——配置文件值注入
  6. 供应商与客户 连接平台 的谋合
  7. crackme 004
  8. 电脑怎么分成两个屏幕,显示不同的内容
  9. 【ZigBee】JN5169 ZigBee3.0设备入网过程
  10. 自己合成制作支付宝、微信、QQ三合一万能收款码
  11. 如何去掉word文档右侧的竖线
  12. 如何在阿里云上创建安全的远程工作空间
  13. MPU6050初始化失败原因及常见问题解决方法
  14. 人像优化效果Lr预设
  15. 关于RuntimeError: Cannot re-initialize CUDA in forked subprocess和CUDA error: initialization error的解决
  16. 数字方法--按零补位
  17. DBCO-PEG-DPPE DBCO-二棕榈酰基磷脂酰乙醇胺-聚乙二醇
  18. “单向网闸”技术介绍
  19. 各种github浏览器无法访问问题
  20. 记录:起个撒名了, 就叫 《方向》 吧....

热门文章

  1. Sonar LTS 版本 8.9发布|新特性
  2. 将中国标准时间转化为 yy-mm-dd hh:mm:ss格式
  3. 自动跳转手机版和电脑版html代码,分享两个手机访问pc网站自动跳转手机端网站代码...
  4. Android 图片动画
  5. 一个线程死掉就等于整个进程死掉
  6. 软件测试的学习笔记(4)
  7. 使用Intellij IDEA的Bookmarks
  8. python个人信息
  9. 中小型医院基础网络解决方案
  10. 吸取“3.21”爆炸事故经验,仓库安全管理的几点要素