Java--多线程--Thread类+Runnable接口

1.多进程与多线程

1.1多进程:

        一个进程是一个包含自身地址的程序,每个独立执行的程序都称为进程,也就是正在执行的程序,系统可以分配给每个进程一段有限的使用CPU的时间(CPU时间片),CPU在这个时间段中执行某个进程,然后下一个时间片又会跳至另一个进程中去执行;由于CPU转换很快,所以使得每个进程好像是在同时执行一样。

1.2多线程:

        Java语言提供了并发机制,程序中可以执行多个线程,每个线程完成一个功能,并于其他线程并发执行,这种机制被称为多线程。

        一个线程则是进程中的执行流程,一个进程中可以同时包括多个线程,每个线程可以得到一下段程序的执行时间,这样一个进程就可以具有多个并发执行的线程。

2.实现线程的2种方式

2.1 继承Thread类

        继承java.lang.Thread类,从这个类中实例化的对象代表线程,启动一个新线程需要建立一个Thread实例。构造方法:

2.1.1 public Thread()

        创建一个新的线程对象。

2.1.2 public Thread(String threadName)

        创建一个名为threadName的线程对象。

public class ThreadTest extends Thread{

        //

}

2.1.3 run()方法:

        完成线程真正功能的代码凡在类的run()方法中,当一个类继承Thread类后,就可以重写覆盖run()方法;

        run()方法必须使用一下语法:

public void run(){

        //

}

2.1.4 start()方法:

        调用Thread类中的strat()方法启动执行线程,start()方法会调用run()方法。

 public static void main(String[] args){

        new ThreadTest().start();

}

主方法main()线程的启动是由Java虚拟机负责的,我们只需要负责自动自己定义的线程即可。

package threadwork;public class CountThread extends Thread {        //指定继承Thread类private int count = 10;public void run() {          //重写run()方法while (true) {System.out.print(count + " ");if (--count == 0) {     //count自减return;}}}public static void main(String[] args) {CountThread ct = new CountThread();     //实例化线程对象ct.start();         //启动线程}
}输出:10 9 8 7 6 5 4 3 2 1 

2.2 实现Runable接口

        Thread 是类,而Runnable是接口;Thread本身是实现了Runnable接口的类。我们知道“一个类只能有一个父类,但是却能实现多个接口”,因此Runnable具有更好的扩展性;如果我们定义的类相想要继承其他类(非Thread类),并且还要当前定义的类实现多线程,可以通过Runnable接口来实现。

        此外,Runnable还可以用于“资源的共享”。即,多个线程都是基于某一个Runnable对象建立的,它们会共享Runnable对象上的资源。

        实际上,Thread类就是实现了Runnable接口,Thread类中的run()方法也是对Runnable接口中的run()方法的实现。

2.2.1 语法:

public class MyDemo extends Object implents Runable{

        //

2.2.2 继承Thread类实现多线程

package threadwork;class Ticket extends Thread {public void run() {for (int ticket = 10; ticket > 0; ticket--) {System.out.println(this.getName() + " 买票:ticket" + ticket);}}
}public class TicketThreadTest {public static void main(String[] args) {Ticket tt_1 = new Ticket();Ticket tt_2 = new Ticket();Ticket tt_3 = new Ticket();tt_1.start();tt_2.start();tt_3.start();}
}输出:Thread-0 买票:ticket10Thread-2 买票:ticket10Thread-1 买票:ticket10Thread-2 买票:ticket9Thread-2 买票:ticket8Thread-2 买票:ticket7Thread-2 买票:ticket6Thread-0 买票:ticket9Thread-0 买票:ticket8Thread-2 买票:ticket5Thread-2 买票:ticket4Thread-1 买票:ticket9Thread-2 买票:ticket3Thread-0 买票:ticket7Thread-2 买票:ticket2Thread-1 买票:ticket8Thread-1 买票:ticket7Thread-1 买票:ticket6Thread-2 买票:ticket1Thread-0 买票:ticket6Thread-0 买票:ticket5Thread-1 买票:ticket5Thread-1 买票:ticket4Thread-0 买票:ticket4Thread-0 买票:ticket3Thread-1 买票:ticket3Thread-0 买票:ticket2Thread-1 买票:ticket2Thread-1 买票:ticket1Thread-0 买票:ticket1

2.2.3 实现Runnale接口的多线程

使用Runnable接口启动新的线程步骤如下:

        a.定义的类实现Runnable接口;

        b.定义的类中实现run()方法;

        c.实例化建立Runnable对象(自定义类的对象);

        d.使用参数为Runnable对象的构造方法创建Thread实例;

        e.调用start()方法启动线程;

package threadwork;class TicketR implements Runnable {public void run() {for (int ticket = 0; ticket <= 10; ticket++) {System.out.println(Thread.currentThread().getName() + " 买票:ticket" + ticket);}}
}public class TicketRunable {public static void main(String[] args) {TicketR ticket_R = new TicketR();Thread t1 = new Thread(ticket_R);Thread t2 = new Thread(ticket_R);Thread t3 = new Thread(ticket_R);t1.start();t2.start();t3.start();}
}输出:Thread-1 买票:ticket0Thread-1 买票:ticket1Thread-1 买票:ticket2Thread-1 买票:ticket3Thread-1 买票:ticket4Thread-1 买票:ticket5Thread-1 买票:ticket6Thread-1 买票:ticket7Thread-0 买票:ticket0Thread-0 买票:ticket1Thread-0 买票:ticket2Thread-2 买票:ticket0Thread-0 买票:ticket3Thread-0 买票:ticket4Thread-0 买票:ticket5Thread-1 买票:ticket8Thread-1 买票:ticket9Thread-1 买票:ticket10Thread-0 买票:ticket6Thread-2 买票:ticket1Thread-2 买票:ticket2Thread-2 买票:ticket3Thread-2 买票:ticket4Thread-2 买票:ticket5Thread-0 买票:ticket7Thread-2 买票:ticket6Thread-2 买票:ticket7Thread-2 买票:ticket8Thread-2 买票:ticket9Thread-2 买票:ticket10Thread-0 买票:ticket8Thread-0 买票:ticket9Thread-0 买票:ticket10

3.线程的生命周期

        虽然多线程看起来像同时执行,但事实上单个CPU在同一时间点上只有一个线程在被执行,只是线程之间切换较快,才有同时执行的假象。

3.1 线程具有7种声明周期:

        1.出生状态、2.就绪状态、3.运行状态、4.等待状态、5.休眠状态、6.阻塞状态、7.死亡状态。

当线程的run()方法执行完毕时,线程会进入死亡状态。

3.2 使线程处于就绪状态的方法:

        3.2.1调用sleep()方法:

        当线程调用Thread类中的sleep()方法时,则会进入休眠状态;

        3.2.2 调用wait()方法:

        当处于运行状态下的线程调用Thread类中的wait()方法时,该线程就会进入等待状态。

        3.2.3 等待输入/输出完成;

        当运行中线程在运行状态下发出I/O请求,该线程会进入阻塞状态,I/O结束时线程会进入就绪状态,对于阻塞的线程来说,既是系统资源空闲,线程依然不能回到运行状态。

3.3 使线程从就绪状态-->运行状态的方法:

        3.3.1 线程调用notify()方法:

        进入等待状态的线程必须调用Thread类中的notify()方法才能被唤醒;

        3.3.2 线程调用notifyAll()方法:

        将所有处于等待状态下的线程唤醒;

        3.3.3 线程调用interrupt()方法:

        3.3.4 线程的休眠时间结束;

        3.3.5 输入/输出结束;

4.操作线程的方法

4.1 线程的休眠:sleep()方法

        sleep()方法参数为毫秒为单位的时间,同时在run()方法中循环被使用。

try{

        Thread.sleep(2000);        //线程休眠等待2秒

}catch(InterruptException e){

        e.printStackTrace();

}

上述代码使线程在2S之内不会进入就绪状态;虽然使用了sleep()方法的线程在一段时间内会醒来,但是并不能保证醒来后它就会进入运行状态,只能保证它进入就绪状态。 

4.2 线程的加入:join()方法

        当一个线程使用join()方法加入另外一个线程时,另外一个线程会等待这个加入的线程执行完毕后再继续执行;

        通常用于在main()主线程内,等待其它子线程完成再接着执行main()主线程;

4.3 线程的中断:布尔型标记控制

        以前会使用stop()方法来停止线程,但是JDK不推荐使用此方法,提倡在run()方法中使用无限循环的形式,然后使用一个布尔型标记控制循环的停止。

public class InterruptedTest implements Runnable{

        private boolean isContine = false;        //设置一个标记变量,默认设置为false

        public void run(){                                        //重写run()方法

                while(true){

                        //dosomething

                        if (isContinue){                        //当isContinue变为true时,停止线程

                                break;

                                                }

                                }

                        }

        

        public void setContinue(){

                this.isContinue = true;                //定义设置变量isContinue的方法

        }

}

4.4 线程的礼让:yield()方法

        Thread类中提供了礼让方法yield(),给当前正在运行状态的线程一个提醒,告知它可以将资源礼让给其他线程,但这仅仅是提醒,没有任何机制保证当前线程会礼让资源;

5.线程的优先级

        每个线程都具有各自的优先级,操作系统会根据线程的优先级来决定首先使哪个线程进入运行状态。

5.1 Thread类中成员变量代表了常用优先级:

        5.1.1 Thread.MIN_PRIORITY(常数1)

        5.1.2 Thread.MAX_PRIORITY(常数10)

        5.1.3 Thread.NORM_PRIORITY(常数5)

在默认情况下,优先级都是Thread.NORM_PRIORITY,且每个新产生的线程都会继承父线程的优先级。

5.2 调整线程优先级:setPriority()方法

setPriority()方法的参数为1~10的数值,数值越大,代表优先级越高;

先设置优先级,再start()启动;

package threadwork;class TicketR implements Runnable {public void run() {for (int ticket = 0; ticket <= 2; ticket++) {System.out.println(Thread.currentThread().getName() + " 买票:ticket" + ticket);}}
}public class TicketRunable {public static void main(String[] args) throws InterruptedException {TicketR ticket_R = new TicketR();Thread t0 = new Thread(ticket_R);Thread t1 = new Thread(ticket_R);Thread t2 = new Thread(ticket_R);t0.setPriority(1);     //先设置优先级,再start()启动t0.start();t0.join();      //主线程等待t1线程执行完毕t1.setPriority(4);t1.start();t1.join();      //主线程等待t2线程执行完毕t2.setPriority(10);t2.start();t2.join();      //主线程等待t3线程执行完毕System.out.println("主线程执行结束");}
}

6.线程的同步

        Java提供线程同步机制来防止资源访问的冲突。

6.1 线程安全

 问题示例:

package threadwork;import com.sun.xml.internal.ws.api.ha.StickyFeature;public class ThreadSafeTest implements Runnable {private int tikets = 10;@Overridepublic void run() {while (true) {if (tikets > 0) {try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}tikets--;System.out.println(Thread.currentThread().getName() + " 抢票后剩余票:" + tikets + " 张");}}}public static void main(String[] args) throws InterruptedException {ThreadSafeTest tst = new ThreadSafeTest();Thread t0 = new Thread(tst);Thread t1 = new Thread(tst);Thread t2 = new Thread(tst);t0.start();t1.start();t2.start();}
}输出:Thread-2 抢票后剩余票:8 张Thread-0 抢票后剩余票:8 张Thread-1 抢票后剩余票:8 张Thread-1 抢票后剩余票:6 张Thread-0 抢票后剩余票:6 张Thread-2 抢票后剩余票:5 张Thread-1 抢票后剩余票:2 张Thread-0 抢票后剩余票:2 张Thread-2 抢票后剩余票:2 张Thread-1 抢票后剩余票:1 张Thread-0 抢票后剩余票:0 张Thread-2 抢票后剩余票:-1 张Thread-1 抢票后剩余票:-2 张

6.2 线程同步机制:synchronized关键字

       给共享资源上一道锁, 给定时间只允许一个线程访问共享资源。

        6.2.1 同步块

        语法:

synchronized(Object){

        //

}        

        通常将共享资源的操作放在synchronized定义的区域内,这样当其他线程也想获取到这个锁时,必须等到锁被释放时才能进入到这个区域。 

package threadwork;public class ThreadSafeTest implements Runnable {private int tikets = 10;@Overridepublic void run() {while (true) {synchronized ("") {if (tikets > 0) {try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}tikets--;System.out.println(Thread.currentThread().getName() + " 抢票后剩余票:" + tikets + " 张");}}}}public static void main(String[] args) throws InterruptedException {ThreadSafeTest tst = new ThreadSafeTest();Thread t0 = new Thread(tst);Thread t1 = new Thread(tst);Thread t2 = new Thread(tst);t0.start();t1.start();t2.start();}
}输出:Thread-0 抢票后剩余票:9 张Thread-0 抢票后剩余票:8 张Thread-0 抢票后剩余票:7 张Thread-0 抢票后剩余票:6 张Thread-0 抢票后剩余票:5 张Thread-0 抢票后剩余票:4 张Thread-0 抢票后剩余票:3 张Thread-0 抢票后剩余票:2 张Thread-0 抢票后剩余票:1 张Thread-0 抢票后剩余票:0 张

        6.2.2 同步方法

        语法:

synchronized void funName(){

        //

}

package threadwork;public class ThreadSafeTest implements Runnable {private int tikets = 10;@Overridepublic synchronized void run() {while (true) {if (tikets > 0) {try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}tikets--;System.out.println(Thread.currentThread().getName() + " 抢票后剩余票:" + tikets + " 张");}}}public static void main(String[] args) throws InterruptedException {ThreadSafeTest tst = new ThreadSafeTest();Thread t0 = new Thread(tst);Thread t1 = new Thread(tst);Thread t2 = new Thread(tst);t0.start();t1.start();t2.start();}
}输出:Thread-0 抢票后剩余票:9 张Thread-0 抢票后剩余票:8 张Thread-0 抢票后剩余票:7 张Thread-0 抢票后剩余票:6 张Thread-0 抢票后剩余票:5 张Thread-0 抢票后剩余票:4 张Thread-0 抢票后剩余票:3 张Thread-0 抢票后剩余票:2 张Thread-0 抢票后剩余票:1 张Thread-0 抢票后剩余票:0 张

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django实战项目-学习任务系统-查询列表分页显示

接着上期代码框架&#xff0c;6个主要功能基本实现&#xff0c;剩下的就是细节点的完善优化了。 接着优化查询列表分页显示功能&#xff0c;有很多菜单功能都有查询列表显示页面情况&#xff0c;如果数据量多&#xff0c;不分页显示的话&#xff0c;页面展示效果就不太好。 本…

pytorch 笔记:GRU

1 介绍 对于输入序列中的每个元素&#xff0c;每一层都计算以下函数&#xff1a; ht​ 是t时刻 的隐藏状态xt​ 是t时刻 的输入ht−1​ 是 t-1时刻 同层的隐藏状态或 0时刻 的初始隐藏状态rt​,zt​,nt​ 分别是重置门、更新门和新门。σ 是 sigmoid 函数∗ 是 Hadamard 乘积。…

OpenCV 笔记(4):图像的算术运算、逻辑运算

Part11. 图像的算术运算 图像的本质是一个矩阵&#xff0c;所以可以对它进行一些常见的算术运算&#xff0c;例如加、减、乘、除、平方根、对数、绝对值等等。除此之外&#xff0c;还可以对图像进行逻辑运算和几何变换。 我们先从简单的图像加、减、逻辑运算开始介绍。后续会有…

【Git企业开发】第四节.Git的分支管理策略和bug分支

文章目录 前言一、Git的分支管理策略 1.1 Fast forward 模式和--no-ff 模式 1.2 企业分支管理策略二、bug分支三、删除临时分支四、总结总结 前言 一、Git的分支管理策略 1.1 Fast forward 模式和--no-ff 模式 通常合并分支时&#xff0c;如果可能&#xff0c;Git 会…

61. 旋转链表、Leetcode的Python实现

博客主页&#xff1a;&#x1f3c6;李歘歘的博客 &#x1f3c6; &#x1f33a;每天不定期分享一些包括但不限于计算机基础、算法、后端开发相关的知识点&#xff0c;以及职场小菜鸡的生活。&#x1f33a; &#x1f497;点关注不迷路&#xff0c;总有一些&#x1f4d6;知识点&am…

基于GEE云平台一种快速修复Landsat影像条带色差的方法

这是之前关于去除遥感影像条带的另一篇文章&#xff0c;因为出版商推迟了一年发布&#xff0c;所以让大家久等了。这篇文章的主要目的是对Landsat系列卫星因为条带拼接或者镶嵌产生的条带来进行的一种在线修复方式。 原文连接 一种快速修复Landsat影像条带色差的方法 题目&a…

ffmpeg命令帮助文档

一&#xff1a;帮助文档的命令格式 ffmpeg -h帮助的基本信息ffmpeg -h long帮助的高级信息ffmpeg -h full帮助的全部信息 ffmpeg的命令使用方式&#xff1a;ffmpeg [options] [[infile options] -i infile] [[outfile options] outfile] 二&#xff1a;将帮助文档输出到文件 …

【IDEA】设置sql提示

第一步&#xff1a;注入SQL语言 1.首先选择任意一条sql语句&#xff0c;右击&#xff0c;选择 ‘显示上下文操作’ 2.选择 ‘注入语言或引用’ 3. 往下翻&#xff0c;找到MySQL 第二步&#xff1a;配置MySQL数据库连接 1.首先点击侧边的数据库&#xff0c;再点击上面的加号 2…

中兴路由器、小米路由器无线信号强度对比

最近小米新推出的路由器小米AX3000T非常火&#xff0c;在网上看到有好多人都在安利&#xff0c;引起了我的兴趣&#xff0c;刚好老家的路由器用了这么久也是时候要换一个了&#xff0c;毕竟我妈老说上网卡??所以我立马就在PDD搞了一台回来&#xff0c;打算和我现在家里用的中…

二叉树进阶 - (C++二叉搜索树的实现)

二叉树进阶 - &#xff08;二叉搜索树的实现&#xff09; 二叉搜索树1. 二叉搜索树概念2. 二叉搜索树操作2.1 二叉搜索树的查找2.2 二叉搜索树的插入2.3 二叉搜索树的删除(重点) 3. 二叉搜索树的(代码)实现 二叉搜索树 1. 二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0…

腾讯云域名备案后,如何解析到华为云服务器Linux宝塔面板

一、购买域名并且进行备案和解析&#xff0c;正常情况下&#xff0c;购买完域名&#xff0c;如果找不到去哪备案&#xff0c;可以在腾讯云上搜索“备案”关键词就会出现了&#xff0c;所以这里不做详细介绍&#xff0c;直接进行步骤提示&#xff1a; 二、申请ssl证书&#xff0…

diffusers-Load adapters

https://huggingface.co/docs/diffusers/main/en/using-diffusers/loading_adaptershttps://huggingface.co/docs/diffusers/main/en/using-diffusers/loading_adapters 有几种训练技术可以个性化扩散模型&#xff0c;生成特定主题的图像或某些风格的图像。每种训练方法都会产…

关于嵌入式rtthread系统与单片机芯片

简介 我估计已经有很久没更新了&#xff0c;近一年都在某个国企里工作&#xff0c;我做的就是嵌入式工程师的岗位&#xff0c;最近才刚刚退出来&#xff0c;想来说说自己的工作使用的软件和系统。 本身进公司的时候&#xff0c;其实做的就是写单片机的板子的程序的工作&#x…

mysql迁移data目录(Linux-Centos)

随着时间的推移&#xff0c;mysql的数据量越越大&#xff0c;使用yum默认安装的目录为系统盘 /var/lib/mysql&#xff0c;现重新挂载了一个硬盘&#xff0c;需要做数据目录的迁移到 /mnt/data/。以解决占用系统盘过高情况。 1.强烈建议这种操作。镜像一个一样的Centos系统&…

基于springboot实现游戏分享网站系统项目【项目源码+论文说明】

基于springboot实现游戏分享网站演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把游戏分享管理与现在网络相结合&#xff0c;利用java技术建设游戏分享网站&#xff0c;实现游戏分享的信息化。则对于进一步提高游戏分享管理发展&#xff0c;丰富游戏分享管理经验能起到…

canvas实现环形进度条

与setTimeout和setInterval不同&#xff0c;requestAnimationFrame不需要设置时间间隔。 效果图 源代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Canvas progress</title> </head&g…

软件测试/测试开发丨ChatGPT能否成为PPT最佳伴侣

点此获取更多相关资料 简介 PPT 已经渗透到我们的日常工作中&#xff0c;无论是工作汇报、商务报告、学术演讲、培训材料都常常要求编写一个正式的 PPT&#xff0c;协助完成一次汇报或一次演讲。PPT相比于传统文本的就是有布局、图片、动画效果等&#xff0c;可以给到观众更好…

Qt 窗口无法移出屏幕

1 使用场景 设计一个缩进/展开widget的效果&#xff0c;抽屉效果。 看到实现的方法有定时器里move窗口&#xff0c;或是使用QPropertyAnimation。 setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint |Qt::X11BypassWindowManagerHint&#xff09;&#xff1b; 记得在移…

linux笔记总结-基本命令

参考&#xff1a; 1.Linux 和Windows比 比较 &#xff08;了解&#xff09; 1. 记住一句经典的话&#xff1a;在 Linux 世界里&#xff0c;一切皆文件 2. Linux目录结构 /lib • 系统开机所需要最基本的动态连接共享库&#xff0c;其作用类似于Windows里的DLL文件。几 乎所有…

企业采用生成式人工智能需要考虑什么

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 最近&#xff0c;各行业采用人工智能生成内容&#xff08;AIGC&#xff09;的趋势显着。这种变革性技术的一些著名实施包括Notion AI…