JUC之线程、线程池

一、start与run方法

start方法开启一个新线程,异步执行。

run方法同步执行,不会产生新的线程。

start方法只能执行一次,run方法可以执行多次。

二、一些方法

sleep() 线程睡眠

两种方式调用:

Thread.sleep(1000);

TimeUnit.SECONDS.sleep(1);

线程打断

interrupt()这种方式打断,线程会抛出InterruptedException异常。比如在线程睡眠的时候,调用interrupt(),线程抛出异常。抛出InterruptedException异常的时候会清除中断标记。

interrupt()方法仅仅是将线程的中断状态设置为true,并不会停止线程。

thread.interrupt();

还有两个方法

isInterrupted()判断当前线程是否被打断,不会清除打断标记。

interrupted();判断当前线程是否被打断,清除打断标记,静态方法。清除打断标记就是恢复线程的 中断状态。也就是说,在调用Thread.interrupted()方法之后,如果中断了此线程,则不会抛出中断异常,但是如果第二次调用Thread.interrupted()方法的话直接返回false,除非有第二次中断触发。

boolean isInterrupted = thread.isInterrupted();

boolean interrupted = Thread.interrupted();

yield()线程让步

只是让出CPU资源,停止执行当前线程的动作,当前线程的状态回到可运行状态。但是当前线程做出让步以后,下一个CPU资源会在哪个线程的身上,取决去调度器,调度器会在同等优先级的线程之间选择一个分配资源。

设置/获取优先级

优先级设置越大,获得CPU资源的可能性就越高。默认优先级使5,最小1,最大10。

thread.setPriority(10);

int priority = thread.getPriority();

join()等待线程结束

join()

join(long time)

上述两个方法都是等待线程结束,即在执行的地方先等待子线程运行结束再往下继续运行主线程。带参数的是最大等待时间,时间一到则不再等待子线程,主线程继续往下运行。一些场景就是主线程运行依赖于子线程的运行结果。

isAlive()

当前线程是否存活

守护线程

线程分为守护线程和用户线程。默认为用户线程。

setDaemon(boolean on)设置当前线程为守护线程

isDaemon()判断当前线程是否为守护线程。

线程的几种状态和转换

创建线程的三种方式

1、继承Thread类

Thread t = new MyThread();
t.start();

public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("my thread");
        }
}

这种方式是继承的方式,因为java是单继承,所以一般用的不多。

2、实现Runnable,重写run()方法

Thread t1 = new Thread(new RunnableThread());
t1.start();

public static class RunnableThread implements Runnable {
        @Override
        public void run() {
            System.out.println("runnable thread ... ");
        }
    }

这种实现接口的方式推荐使用

3、实现callable,重写call()方法

实现callable的方式,重写的call方法有返回值,这点和Runnable的接口有所不同,并且是交给FutureTask管理,通过future.get()可以获得call()方法的返回值。

注意的是,调用future.get()方法的时候,线程会等待call()方法执行完成,拿到返回值以后才会继续往下执行。

FutureTask futureTask = new FutureTask(new CallableThread());
futureTask.run();
String res = (String) futureTask.get();


public static class CallableThread implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println("callable thread ... ");
            TimeUnit.SECONDS.sleep(5);
            return "callable";
        }
    }

如果不需要返回值的话,用的最常见的就是第二种实现Runnable的方式,并且用lambda的方式,比如:

new Thread(()->{
            System.out.println("thread start ...");
        }).start();

线程池

集中管理线程,节省资源,线程复用,减少开销,便于维护。

Executors提供了固定的几种线程池的创建方式。

1、Executors.newFixedThreadPool(5);创建固定大小的线程池,参数是线程数量

2、Executors.newSingleThreadExecutor();创建只有一个线程数量的线程池
3、Executors.newCachedThreadPool();创建可以扩容的线程池,会一直增加线程数量,不建议使用。

上述3中线程池执行方法:

executorService.execute(()->{});传入Runnable对象

4、Executors.newScheduledThreadPool(5);创建有定时任务的线程池

这种线程池执行的方式scheduledExecutorService.schedule(()->{},5,TimeUnit.SECONDS);

第一个参数是Runnable对象,第二个参数是延迟时间,第三个参数是时间单位。

关闭线程池

shutdown(),等待所有的任务执行完毕关闭线程池。

shutdownNow(),等待正在执行的任务执行完毕后关闭线程池。

awaitTermination(10, TimeUnit.SECONDS),等待所有任务执行完毕,或者超时以后线程池关闭

isTerminated()线程池是否关闭

线程池的execute和submit方法区别

1、参数不同

execute()方法接收的是Runnable参数

submit接收的是Runnable或者Callable参数

2、返回值不同

execute()方法没有返回值

submit方法有返回值,返回的是Future类型,通过future.get()获得具体的结果。

注意:如果execute传入的是FutureTask类型的话,其实也是可以接收返回结果的。只不过submit替我们封装了FutureTask。

ExecutorService executorService = Executors.newFixedThreadPool(5);
Future<String> future = executorService.submit(() -> {
      return "123";
 });
 String s = future.get();
 System.out.println("s " + s);



 FutureTask<String> futureTask = new FutureTask(() -> {
      return "hello";
 });
 executorService.execute(futureTask);
 System.out.println("futuretask " + futureTask.get());

3、异常捕捉

execute()执行的子线程中的异常,只能子线程进行处理,主线程无法处理,即无法进行 程序的统一异常处理。

submit()中子线程的异常可以在主线程中进行统一异常处理,因为子线程出现异常的时候,并不会立即报错,在进行future.get()进行获取结果的时候才抛出异常,所以主线程可以进行统一异常处理。

自定义线程池

参数

corePoolSize:核心线程数

maximumPoolSize:最大线程数

keepAliveTime:非核心线程空闲状态存活时间

unit:存活时间单位

workQueue:工作/阻塞队列,

线程先加入到核心线程,核心线程数量达到以后,就会加入到阻塞队列,当阻塞队列满了以后加入非核心线程。

threadFactory:线程工厂

handler:拒绝策略

当线程已经超过了最大线程数加上阻塞队列的数量,就会触发拒绝策略

有四种拒绝策略:

AbortPolicy:拒绝新任务并抛出异常

DiscardPolicy:丢弃任务,不会抛异常

DiscardOldestPolicy:丢弃老的未处理的任务,新的任务加入队列

CallerRunsPolicy:自己处理新的任务,处理的逻辑在传入的Runnable方法中实现。

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,
                3,
                0,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        try {
            for (int i = 0; i < 50; i++) {
                Task task = new Task(i);
                threadPoolExecutor.submit(task);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPoolExecutor.shutdown();
        }
public static class Task implements Runnable {
        int i;

        public Task(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thread: "+Thread.currentThread().getName()+" ... ...");
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/576663.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kafka 3.x.x 入门到精通(06)Kafka进阶

Kafka 3.x.x 入门到精通&#xff08;06&#xff09;——对标尚硅谷Kafka教程 3. Kafka进阶3.1 Controller选举3.2 Broker上线下线3.3 数据偏移量定位3.4 Topic删除3.5 日志清理和压缩3.7 页缓存3.8 零拷贝3.9 顺写日志3.10 Linux集群部署3.10.1 集群规划3.10.2 安装虚拟机(略)3…

Ubuntu下载的nginx的位置

位置在/etc/nginx 启动nginx systemctl status nginx上面的命令不合适&#xff0c;就重启nginx sudo service nginx restart 关闭nginx nginx -s stop Ubuntu默认的html地址在该文件夹中的default中&#xff1a; /etc/nginx/sites-available if ($http_host ~* "^(w…

怎么用AI绘画进行人物修复?

用过AI绘画生成人物图片的朋友们是不是都碰到过这样的问题&#xff1a;诡异的造型、崩坏的五官、离谱的手指头、乱七八糟的背景...指望AI一次性生成百分百完美的图貌似有点难啊。 现在AI绘画有了【脸部修复】【手部修复】功能&#xff0c;就能够轻松解决这些的问题了&#xff0…

ESLint 、 e2e test 学习

Lint和Format的区别&#xff1a; Lint只会告诉你代码中的错误或者不符合规范的地方&#xff0c;而Format是用来对格式作调整的 HTML/tpl&#xff1a;HTMLLint CSS/SCSS&#xff1a;Stylelint JS/JSX&#xff1a;Eslint JSLint&#xff1a;古老&#xff0c;不能配置和扩展JSHin…

十几款必备AI写作软件!涵盖国内国外,免费在线一键生成原创文案文章!

今天&#xff0c;就让我带您领略市面上那些备受瞩目的10款AI写作神器&#xff0c;一同探索哪款工具 将成为您创作旅程中的得力助手。首先&#xff0c;让我们揭开这些A1写作工具的神秘面纱 深入了解它们的基本功能。这些工具如同智慧之笔&#xff0c;能够迅速为您生成文章、段 落…

工作记录:vue-grid-layout 修改 margin 导致 item 高度剧烈变化

问题 用 vue-gird-layout 时发现&#xff0c;当改变 margin 值时&#xff0c;item 的尺寸也会跟着变化。 如下图&#xff1a;row height 和每个 item 的 h 都保持不变。修改 margin-y&#xff0c;item 的实际高度也跟着变了&#xff1a; 原因 研究了一番&#xff0c;发现原…

MySql 主从同步-在原来同步基础上增加历史数据库

在MySql已经主从同步的后&#xff0c;由于有新的需求再增加1个历史数据库&#xff0c;要改原来的1个变成现在的2个数据库。在官网并没有找到类似的场景&#xff08;官方同步多个数据是从一开始就设置&#xff0c;不是后续增加的&#xff09;&#xff0c;只能结合以往的经验自己…

《HCIP-openEuler实验指导手册》1.6 Apache静态资源配置

知识点 常用用途&#xff1a; 软件仓库镜像及提供下载服务&#xff1a; 配置步骤 删除网站主目录中的文件&#xff08;本实验机目录为/home/source ip为192.168.12.137 端口为81&#xff09; cd /home/source rm -rf *在主目录中新建6个文件夹如下图 mkdir test{1..6}新建…

VTK----VTK数据结构详解3(代码篇)

上篇文章&#xff08;VTK----VTK数据结构详解&#xff08;计算机篇&#xff09;-CSDN博客&#xff09;从计算机数据结构&#xff08;数组、链表等&#xff09;的角度对数据数组、数据对象、数据属性的实现原理进行了说明&#xff0c;下面从代码的层面详细说明它们的使用及相关实…

ssm082基于java斗车交易系统设计与实现+vue

斗车交易系统 摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&…

12.Blender 界面介绍(上)及物体基础编辑操作

设置语言 首先在菜单栏打开编辑-Preferences-界面-翻译&#xff0c;可以修改语言 这里使用的是Steam上下载的4.1版本 工具栏 左边的工具栏&#xff0c;按T就会出现&#xff0c;再按T就会隐藏 右边的工具栏是按N&#xff0c;按N显示&#xff0c;再按N隐藏 旋转画面 长按鼠…

C语言面试题之相交链表

相交链表 实例要求 1、给定两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。2、如果两个链表不存在相交节点&#xff0c;返回 null 。示例&#xff1a; 实例分析 可以使用两种方法&#xff1a;哈希表方法和双指针方法。哈希表方法…

Golang基础7-并发编程

并发编程 https://www.cnblogs.com/Survivalist/p/11527949.html 进程和线程、协程的区别_线程协程进程的区别-CSDN博客 Golang中的并发编程是一个重点&#xff0c;我们要了解Golang中的并发Goroutine因此需要先理解进程、线程、之后再理解协程。 进程&#xff1a;操作系统进…

某翻译平台翻译接口逆向之webpack学习

逆向网址 aHR0cHM6Ly9mYW55aS55b3VkYW8uY29tLw 逆向链接 aHR0cHM6Ly9mYW55aS55b3VkYW8uY29tLyMv 逆向接口 aHR0cHM6Ly9kaWN0LnlvdWRhby5jb20vd2VidHJhbnNsYXRl 逆向过程 请求方式 POST 逆向参数 sign c168e4cb76169e90f82d28118dbd24d2 接口请求结果解密 过程分析 根据XHR…

免费获取!遗传算法+多目标规划算法+自适应神经模糊系统程序代码!

前言 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世纪70年代提出&#xff0c;该算法是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型&#xff0c;通过数学的方式&#xff0c;将问题的求解过程转…

全国省级金融发展水平数据集(2000-2022年)

01、数据简介 金融发展水平是一个国家或地区经济实力和国际竞争力的重要体现。它反映了金融体系的成熟程度和发展水平&#xff0c;是衡量一个国家或地区经济发展质量的重要指标。金融发展水平的提高&#xff0c;意味着金融体系能够更好地服务实体经济&#xff0c;推动经济增长…

3.7设计模式——Observer 观察者模式(行为型)

意图 定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于他的对象都得到通知并被自动更新。 结构 Subject&#xff08;目标&#xff09;知道它的观察者&#xff0c;可以有任意多个观察者观察同一个目标&#xff0c;提供注册和删…

模块三:二分——153.寻找旋转排序数组中的最小值

文章目录 题目描述算法原理解法一&#xff1a;暴力查找解法二&#xff1a;二分查找疑问 代码实现解法一&#xff1a;暴力查找解法二&#xff1a;CJava 题目描述 题目链接&#xff1a;153.寻找旋转排序数组中的最小值 根据题目的要求时间复杂度为O(log N)可知需要使用二分查找…

电子负载仪的远端控制

前言 最近研究了电子负载仪的远端控制&#xff08;区别于前面板控制&#xff09;&#xff0c;主要是用于程序控制&#xff0c;避免繁琐复杂的人工控制&#xff0c;举了南京嘉拓和艾维泰科的例子。 有纰漏请指出&#xff0c;转载请说明。 学习交流请发邮件 1280253714qq.com …

基于JavaWEB的学生考勤管理系统(含论文)

本系统是用Java语言写的&#xff0c;基于JavaWEB的学生考勤管理系统 主要有三大模块&#xff0c;学生&#xff0c;教师和管理员模块&#xff0c;功能如下&#xff1a; 学生模块 教师模块&#xff1a; 管理员模块
最新文章