多线程简述
2021/5/1 18:25:25
本文主要是介绍多线程简述,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
多线程
- 一、多线程概述
- 1.线程与进程
- 2.线程调度
- 3.同步与异步
- 4.并发与并行
- 二、多线程实现
- 1.继承Thread类
- 2.实现Runnable接口
- 3.实现Callable接口
- 三、线程池
- 1.CachedThreadPool
- 2.FixedThreadPool
- 3.SingleThreadExecutor
- 4.ScheduledThreadPool
提示:以下是本篇文章正文内容
一、多线程概述
1.线程与进程
a.线程
- 是进程中的一条执行路径,共享一个内存空间,线程之间可以自由切换,并发执行。一个进程至少有一个线程
- 线程实际上是在进程基础上的进一步划分,一个进程启动之后,里面若干执行路径又可以划分为若干线程
b.进程
- 是指一个内存中运行的应用程序,每一个进程都有一个独立的内存空间
2.线程调度
a.分时调度(轮流)
- 所有线程轮流使用CPU 的使用权,平均分配每个线程占用 CPU 的时间
b.抢占式调度(抢)
- 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
- CPU使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核新而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是 在同一时刻运行。其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的 使用率更高。
3.同步与异步
a.同步
- 排队执行、 效率低、安全
b.异步
- 同时执行、效率高、数据不安全
4.并发与并行
a.并发
- 指两个或多个事件在同一个时间段内发生
b.并行
- 指两个或多个事件在同一时刻发生(同时发生)
二、多线程实现
1.继承Thread类
继承Thread、重写run()
public class MyThread extends Thread{ /** * run方法就是线程要执行的任务方法 */ @Override public void run() { //这里的代码,就是一条新的执行路径 //这个执行路径的触发方式,不是调用run方法,而是通过thread对象的start()来启动任务 for (int i=0;i<10;i++){ System.out.println("我是本线程要执行的任务"+i); } } }
创建继承Thread的类对象,使用start()启动线程
public class ThreadDemo { public static void main(String[] args) { //Thread MyThread m = new MyThread(); m.start(); for (int i=0;i<10;i++){ System.out.println("我是主线程的任务"+i); } //每个线程都拥有自己的栈空间,共用一份堆内存 m.run(); //常用Thread类构造方法 //Thread() //Thread(Runnable),一参传一个任务 //Thread(Runnable,name),二参,一个传一个任务,一个传线程名字 //常用的Thread类方法 //getName //getId //getPriority 获取线程优先级 //setPriority 设置线程优先级 //关于线程优先级 有三个常量 大、小、默认 //start //stop 已过时 方法不安全 //结束线程 可以 声明一个变量来标记 变量改变则结束线程 //sleep(1000) 休眠 暂时停止 //上面是线程休眠1s的方法 //setDaemon 标记 守护线程 或 用户线程 //守护线程:守护线程不能控制自己的生命,守护线程依附于用户线程,用户线程结束,守护线程自动死亡 //用户线程:用户线程即不管是mian线程还是子线程未执行结束 程序都不会结束的线程 都称为用户线程 //mian线程是主线程,其他为子线程 } }
2.实现Runnable接口
实现Runnable接口,重写run()
public class MyRunnable implements Runnable{ @Override public void run() { for (int i=0;i<10;i++){ System.out.println(i+"床前上天窗"); } } }
创建任务对象,创建线程并分配任务,start()启动线程
public class RunnableDemo { public static void main(String[] args) { //实现Runnable //1. 创建任务对象 MyRunnable r = new MyRunnable(); //2. 创建一个线程,并为其分配一个任务 Thread t = new Thread(r); //3. 执行这个线程 t.start(); for (int i=0;i<10;i++){ System.out.println("底下没有光"+i); } //这里是创建匿名Thread对象 的方式创建一个一次性线程 new Thread(){ @Override public void run() { for (int i=0;i<10;i++){ System.out.println("匿名类一次性线程"+i); } } }.start(); } }
实现Runnable 与 继承Thread相比的优势:
1. 通过创建任务,然后给线程分配的方式来实现的多线程。更适合多个线程同时执行相同任务的情况 2. 可以避免单继承所带来的局限性 3. 任务与线程本身是分离的,提高了程序的健壮性 4. 后线程池技术,接受Runnable类型的任务,不接受Thread类型的线程
3.实现Callable接口
有返回值的线程Callable
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class MakeThreadByCallable { public static void main(String[] args) throws InterruptedException, ExecutionException { Callable<Integer> c = new MyCallable(); FutureTask<Integer> task = new FutureTask<>(c); new Thread(task).start(); /** * task.isDone(); //判断子线程是否执行完毕 * task.cancel(); //参数为布尔类型的 */ int callableNum = task.get(); System.out.println("----------------"); System.out.println(callableNum); System.out.println("----------------"); for (int i=0;i<10;i++){ Thread.sleep(100); System.out.println(Thread.currentThread().getName()+i); } } static class MyCallable implements Callable<Integer>{ @Override public Integer call() throws Exception { for (int i=0;i<10;i++){ Thread.sleep(100); System.out.println(Thread.currentThread().getName()+i); } return 100; } } }
三、线程池
1.CachedThreadPool
CachedThreadPool:缓存线程池(长度无限制)
任务加入后的执行流程:
- 判断线程池是否存在空闲线程
- 存在则用
- 不存在,则创建线程 并放入线程池,然后使用
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CachedThreadPoolDemo { public static void main(String[] args) throws InterruptedException { //指挥线程池执行新的任务 ExecutorService service = Executors.newCachedThreadPool(); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":锄禾入党无"); } }); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":旱地核下土"); } }); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":清名上河图"); } }); Thread.sleep(2000); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":旱地核下土"); } }); } }
2.FixedThreadPool
FixedThreadPool:定长线程池(长度是指定任务的数值)
任务加入后的执行流程:
- 判断线程池是否存在空闲线程
- 存在则使用
- 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池,然后使用
- 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class FixedThreadPoolDemo { public static void main(String[] args) { ExecutorService service = Executors.newFixedThreadPool(2); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":锄禾入党无"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":旱地核下土"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":清名上河图"); } }); } }
3.SingleThreadExecutor
SingleThreadExecutor:单线程线程池
执行流程:
- 判断线程池 的那个线程 是否空闲
- 空闲则使用
- 不空闲,则等待 池中的单个线程空闲后 使用
package ThreadTrain; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class SingleThreadExecutorDemo { public static void main(String[] args) { ExecutorService service = Executors.newSingleThreadExecutor(); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":老子是你儿子"); } }); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":儿子我是你爹"); } }); service.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":老儿我是你爷"); } }); } }
4.ScheduledThreadPool
ScheduledThreadPool:定长线程池(周期任务)
执行流程:
- 判断线程池是否存在空闲线程
- 存在则使用
- 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池,然后使用
- 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
周期性任务执行时:
- 定时执行,当某个时机触发时,自动执行某任务。
package ThreadTrain; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ScheduledThreadPoolDemo { public static void main(String[] args) { ScheduledExecutorService service = Executors.newScheduledThreadPool(2); /** * 方式一 定时执行一次 * 参数1. 定时执行的任务 * 参数2. 时长数字 * 参数3, 时长数字的时间单位,TimeUnit的常量指定 service.schedule(new Runnable() { @Override public void run() { System.out.println("你好兄弟"); } },5, TimeUnit.SECONDS);*/ /** * 周期性执行任务 * 参数1. 任务 * 参数2. 延迟时长数字(第一次执行在什么时间以后) * 参数3. 周期时长数字(每隔多久执行一次) * 参数4. 时长单位数字 */ service.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("旱地核下土"); } },5,1,TimeUnit.SECONDS); } }
这篇关于多线程简述的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26手写消息中间件:从零开始的指南
- 2024-11-26Java语音识别项目资料:新手入门教程
- 2024-11-26JAVA语音识别项目资料:新手入门教程
- 2024-11-26Java语音识别项目资料:入门与实践指南
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料:新手入门教程
- 2024-11-25Java创意资料:新手入门的创意学习指南
- 2024-11-25JAVA对接阿里云智能语音服务资料详解:新手入门指南
- 2024-11-25Java对接阿里云智能语音服务资料详解