java多线程全面解析
文章目录
- 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。
同步监视器的执行过程:
- 第一个线程访问﹐锁定同步监视器﹐执行其中代码。
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多线程全面解析相关推荐
- Java多线程技术解析
Java多线程技术 1.多线程的概述 1.1.进程与线程 进程是操作系统进行资源分配和调度的一个独立单位,它是一个内存中运行的应用程序的载体,每个进程都有一个独立的内存空间.进程一般由程序,数据集合和 ...
- java resume过时方法_学点开发|关于Java多线程用法解析
在进行学习之前,我们先来了解下,什么是Java多线程: 多线程是实现并发机制的一种有效手段.进程和线程一样,都是实现并发的一个基本单位.为了让大家更清晰读懂关于Java多线程用法,由以下几点入手学,帮 ...
- java多线程的安全_【JAVA多线程安全问题解析】
一.问题的提出 以买票系统为例: 1 class Ticket implementsRunnable2{3 public int sum=10;4 public voidrun()5{6 while( ...
- [遇见时光]Java多线程
原博:http://www.codeceo.com/article/java-mult-thread.html,本博文加入自己的理解.更详细参考http://blog.csdn.net/evankak ...
- 【2021最新版】Java多线程并发面试题总结(108道题含答案解析)
文章目录 JAVA并发知识库 1.Java中实现多线程有几种方法? 2.继承Thread类 3.实现Runnable接口. 4.ExecutorService.Callable.Future有返回值线 ...
- 当初我要是这么学习Java多线程就好了「附图文解析」
文章目录 1. 概念篇 1.1 认识进程 1.2 进程性质 1.3 操作系统如何管理进程 1.4 多线程和多进程 1.5 时间片 1.6 并发与并行 1.7 内核态与用户态 1.8 进程中的上下文 1 ...
- Java多线程——Thread Runnable源码解析
Java多线程的两种实现方法大家都应该知道了:继承Thread的子类实例化和实现Runnable接口用这个接口实现类去创建Thread实例. Java的线程在Linux平台上使用的是NPTL机制,JV ...
- java线程内存模型_深度解析Java多线程的内存模型
内部java内存模型 硬件层面的内存模型 Java内存模型和硬件内存模型的联系 共享对象的可见性 资源竞速 Java内存模型很好的说明了JVM是如何在内存里工作的,JVM可以理解为java执行的一个操 ...
- 【Java系列】深入解析Java多线程
序言 你只管努力,其他交给时间,时间会证明一切. 文章标记颜色说明: 黄色:重要标题 红色:用来标记结论 绿色:用来标记一级重要 蓝色:用来标记二级重要 希望这篇文章能让你不仅有一定的收获,而且可以愉 ...
最新文章
- TVM将深度学习模型编译为WebGL
- 捣鼓 Subversion
- leetcode算法题--回文链表
- MySQL数据库是非关系_MySQL(数据库)基础知识、关系型数据库yu非关系型数据库、连接认证...
- idea yml变成文件了_初识SpringBoot之配置文件(二)——配置文件值注入
- 供应商与客户 连接平台 的谋合
- crackme 004
- 电脑怎么分成两个屏幕,显示不同的内容
- 【ZigBee】JN5169 ZigBee3.0设备入网过程
- 自己合成制作支付宝、微信、QQ三合一万能收款码
- 如何去掉word文档右侧的竖线
- 如何在阿里云上创建安全的远程工作空间
- MPU6050初始化失败原因及常见问题解决方法
- 人像优化效果Lr预设
- 关于RuntimeError: Cannot re-initialize CUDA in forked subprocess和CUDA error: initialization error的解决
- 数字方法--按零补位
- DBCO-PEG-DPPE DBCO-二棕榈酰基磷脂酰乙醇胺-聚乙二醇
- “单向网闸”技术介绍
- 各种github浏览器无法访问问题
- 记录:起个撒名了, 就叫 《方向》 吧....