java多线程多态_Java学习之多线程

多线程:

(一)进程与线程

进程特点

f83928721de52a1532597639f856683c.png

并发与并行的区别:

7ea0d92ad3f51bfa73bae07512d425e7.png

多线程编程的好处:

7320fb21ce9e9396fb543c5ba76f963f.png

(二)多线程的建立

1,通过继承Thread类,代码如下:

class MyThread extendsThread {private static int K = 10;//类共享变量

private int M=10;//成员共享变量

MyThread(){super();

}

@Overridepublic voidrun() {

System.out.println("in MyThread run");for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+ "K:" + K--);

System.out.println(Thread.currentThread().getName()+ "M:" + M--);

}

}

}public classThreadDemo1 {public static voidmain(String[] args) {//多线程Thead方式1

MyThread thread2 = newMyThread();new Thread(thread2,"t2").start();//此时成员变量被共享,静态也被共享,k和M的结果为-9

new Thread(thread2,"t3").start();//多线程Thead方式1

MyThread thread3=new MyThread();//此时静态类变量被共享,k为-9,M为0.

thread2.start();

thread3.start();

}

}

2,通过实现Runnable接口(推荐),代码如下:

public classThreadDemo1 {public static voidmain(String[] args) {//RUNNABLE 方式2

MyRunnable myRunnable = newMyRunnable();new Thread(myRunnable,"t1").start();//此时成员变量被共享,静态也被共享,K和M为-9//RUNNABLE 方式2

new Thread(myRunnable,"t3").start();

MyRunnable myRunnable1= new MyRunnable();//此时成员变量不被共享,静态被共享,K为-9,M为0

new Thread(myRunnable,"t1").start();new Thread(myRunnable1,"t3").start();

}

}class MyRunnable implementsRunnable {private static int K = 10;private int M = 10;

@Overridepublic voidrun() {

System.out.println("in MyRunnable run");for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+ " K:" + (K--));

System.out.println(Thread.currentThread().getName()+ " M:" + (M--));

}

}

}

3,通过实现Callable接口和Future包装来建立:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

importjava.util.Random;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.FutureTask;public classCallableThread {public static voidmain(String[] args) {

Callable callable = new Callable() {public Integer call() throwsException {return new Random().nextInt(100);

}

};

FutureTask future = new FutureTask(callable);newThread(future).start();try{

Thread.sleep(5000);//可能做一些事情

System.out.println(future.get());

}catch(InterruptedException e) {

e.printStackTrace();

}catch(ExecutionException e) {

e.printStackTrace();

}

}

}

View Code

三种建立多线程的优劣比较有:

9e8385e9176f429f2315fedafd7d57c5.png

(三)线程的生命周期

5224506f15d23aece54edce9cb0dd03a.png

Java线程具有五中基本状态

新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就     绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

关键字:

yield:该线程让出CPU,进入就绪状态

join:该子线程优先执行,相当于方法调用,父线程进入IO阻塞状态

sleep:该线程让出CPU,进入IO阻塞状态,不释放对象锁

wait:同步锁下进行使用,该线程进入阻塞状态,释放对象锁

notify:唤醒wait下的线程,进入同步阻塞状态

synchronized:同步锁,未获得锁的线程进入同步阻塞状态

(五),多线程同步(Thread Synchronized)

线程同步即保证某个线程访问某个共享资源时,其他的线程需要wait,即有顺序性

(六),多线程案例

1,线程死锁案例:

/*死锁:

线程1:synchronized(o1) { Thread.sleep() synchronized(o2) }

线程2:synchronized(o2) { Thread.sleep() synchronized(o1) }

首先线程1执行,对o1加同步锁,其他线程无法访问,

然后线程1睡眠,让出cpu,线程2执行,锁住o2

线程1睡眠结束,继续执行,要对o2加同步锁,但被线程2占据,所以上不了锁,

处于等待获得o2同步锁的状态,且线程1不能结束,释放不了o1对象。

线程2睡眠结束,继续执行,要对o1加同步锁,但被线程1占据,所以上不了锁,

处于等待获得o1同步锁的状态,且线程2不能结束,故释放不了o2

故处于死锁状态。

死锁经典问题:哲学家问题

方法:加粗锁定对象*/

public class DeadThread implementsRunnable {private int flag=0;static Object object=new Object();//类变量,只有一份,每个实例共享

static Object object1=new Object();// public voidrun(){if (flag==0){synchronized (object) {//释放object同步锁,需要等object1锁释放,

System.out.println(flag);try{

Thread.sleep(40);

}catch(InterruptedException e) {

e.printStackTrace();

}synchronized(object1) {//System.out.println(flag);

}

}

}if (flag==1){synchronized (object1) {//释放object1同步锁,需要等object锁释放.两个线程互相等待中

System.out.println(flag);try{

Thread.sleep(400);

}catch(InterruptedException e) {

e.printStackTrace();

}synchronized(object) {//System.out.println(flag);

}

}

}

}public static voidmain(String[] args) {

DeadThread deadThread=newDeadThread();

DeadThread deadThread1=newDeadThread();

deadThread.flag=0;

deadThread.flag=1;

Thread thread=newThread(deadThread);

Thread thread1=newThread(deadThread1);

thread.start();

thread1.start();

}

}

2,多线程多态:

public classThreadTest {public static voidmain(String[] args) {for (int i = 0; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);if (i == 30) {

Runnable myRunnable= newMyRunnable();

Thread thread= new MyThread(myRunnable);//输出的是MyThread中的Run方法,多态的体现

Thread thread1=new Thread(myRunnalbe);//输出myRunnable中run方法。

thread1.start();

thread.start();

}

}

}

}class MyRunnable implementsRunnable {private int i = 0;

@Overridepublic voidrun() {

System.out.println("in MyRunnable run");for (i = 0; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);

}

}

}class MyThread extendsThread {private int i = 0;publicMyThread(Runnable runnable){super(runnable);

}

@Overridepublic voidrun() {

System.out.println("in MyThread run");for (i = 0; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);

}

}

}

3,生产者消费者模型:

public classProducerConsumer {public static voidmain(String[] args) {

SycnStack ss=newSycnStack();

Runnable producer=newProducer(ss);

Runnable consumer=newConsumer(ss);new Thread(producer,"p1").start();/*new Thread(producer,"p2").start();

new Thread(producer,"p3").start();

new Thread(producer,"p4").start();

new Thread(producer,"p5").start();*/

new Thread(consumer,"c1").start();

}

}classWoTo{intid;

WoTo(intid){this.id=id;

}

@OverridepublicString toString() {return "WOTO"+":"+id;

}

}classSycnStack{

WoTo[] wotoArr=new WoTo[6];int index=0;public synchronized voidpush(WoTo woto){while (index==6){//wotoArr.length==6,当stack中满6个时,生产停止,需要消费者消费并notify生产者继续生产

try{

System.out.println("full");//发生wait后,如果没有notify唤醒写在wait的方法不执行。

this.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

wotoArr[index]=woto;

index+=1;this.notifyAll();//生产往后通知消费者,主要是唤醒消费者来消费,如果多线程也会唤醒生产者,但唤醒后任然可能会进入wait中

}public synchronizedWoTo pop(){while (index==0){try{

System.out.println("null");this.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

index-=1;this.notifyAll();//消费完后通知生产者,唤醒生产者来生产,注释掉会进入死锁状态即,消费者等生产者生产,而生产者在wait中。

returnwotoArr[index];

}

}class Producer implementsRunnable{

SycnStack ss=null;

Producer(SycnStack ss){this.ss=ss;

}

@Overridepublic voidrun() {for (int i=0;i<20;i+=1){//一个线程最多生产20个馒头

WoTo woto=newWoTo(i);

ss.push(woto);try{

Thread.sleep(200);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+":produce:"+woto);

}

}

}class Consumer implementsRunnable{

SycnStack ss=null;

Consumer(SycnStack ss){this.ss=ss;

}

@Overridepublic voidrun() {for(int i=0;i<20;i+=1){//一个消费者最多消费20个

WoTo woto=ss.pop();try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+":consuemer:"+woto);

}

}

}

4,笔试题1:

public class SyncThread1 implementsRunnable {int num=100;/*m1()和m2()都加了同步锁,执行流程显示调用run方法中的m1(),对num加同步锁,然后让出cpu,开始main线程

调用m2方法,不能访问不能修改num,结束然后,输出num,然后让出cpu,继续执行m1()方法。sleep并不代表结束就能马上运行,处于就绪状态

需抢占*/

synchronized voidm1(){

num=1000;try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("num"+num);

}synchronized voidm2(){try{

Thread.sleep(500);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(num);

num=2000;//System.out.println(num);

}public voidrun(){

m1();

}public static voidmain(String[] args) {

SyncThread1 syncThread1=newSyncThread1();

Thread thread=newThread(syncThread1);

thread.start();//新开的线程,不和main线程共线程

syncThread1.m2();//在main线程中,因为m2()加了同步锁,即对num加锁了,m2无法对num修改,即不执行,直接执行下面这个输出

System.out.println(syncThread1.num);//main线程要等syncThread1.m2()执行完才执行

}

}

5,哲学家问题:

/*问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条。哲学家思考问题,

当饿了的时候拿起左右两只筷子吃饭,必须拿到两只筷子才能吃饭。上述问题会产生死锁的情况,

当5个哲学家都拿起自己右手边的筷子,准备拿左手边的筷子时产生死锁现象。

解决办法:

1、添加一个服务生,只有当经过服务生同意之后才能拿筷子,服务生负责避免死锁发生。

2、每个哲学家必须确定自己左右手的筷子都可用的时候,才能同时拿起两只筷子进餐,吃完之后同时放下两只筷子。

代码实现:实现第2种方案*/

public classPhilosopherDemo {public static voidmain(String[] args) {

Fork fork=newFork();//五个philosopher都指向同一个fork,所以此时相当于成员变量被多个线程共享了

Philosopher philosopher=new Philosopher(fork,0);

Philosopher philosopher1=new Philosopher(fork,1);

Philosopher philosopher2=new Philosopher(fork,2);

Philosopher philosopher3=new Philosopher(fork,3);

Philosopher philosopher4=new Philosopher(fork,4);newThread(philosopher).start();newThread(philosopher1).start();newThread(philosopher2).start();newThread(philosopher3).start();newThread(philosopher4).start();

}

}class Philosopher implementsRunnable{

Fork fork=null;intid;

Philosopher(Fork fork,intid){this.fork=fork;this.id=id;

}

@Overridepublic voidrun() {while(true){

think();

fork.getFork(this);

eat();

fork.offFork(this);

}

}public voidthink(){try{

System.out.println(id+"in thinking");

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}public voideat(){try{

System.out.println(id+"in eating");

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}classFork{boolean[] fork={false,false,false,false,false};//模拟五把叉

public synchronized voidgetFork(Philosopher p){while(fork[p.id]||fork[(p.id+1)%5]){

System.out.println("p:"+p.id+"waiting");try{

wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

fork[p.id]=true;

fork[(p.id+1)%5]=true;

System.out.println("p:"+p.id+"getFork");

}public synchronized voidoffFork(Philosopher p){

fork[p.id]=false;

fork[(p.id+1)%5]=false;

System.out.println("p:"+p.id+"offFork");this.notifyAll();

}

}

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

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

相关文章

php seaslog安装,浅谈win10下安装php seaslog扩展的方法

本篇文章给大家分享一下win10 php安装seaslog扩展的方法。有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对大家有所帮助。【推荐学习&#xff1a;《PHP视频教程》】一、检查系统环境情况使用phpinfo()检查系统环境情况&#xff0c;找到需要下载的配置…

php里push的用法,php array_push函数怎么用?

php array_push函数用于向数组尾部插入一个或多个元素&#xff0c;其语法是array_push(array,value1,value2...)&#xff0c;参数array必需&#xff0c;指规定一个数组&#xff1b;value1必需&#xff0c;指规定要添加的值。php array_push函数怎么用&#xff1f;定义和用法arr…

java if (name!=null name!=),java中的NullPointerException异常

java中的NullPointerException异常关注:176 答案:3 mip版解决时间 2021-01-27 20:59提问者侢遇噹姩揂2021-01-27 02:10Login.jsp提供登录表单。到LoginCheck.jsp发生空指针异常错误。LoginCheck.jsp:String userName request.getParameter("userName");String pas…

caany边缘检测matlab,自适应canny算法研究及其在图像边缘检测中的应用.pdf

自适应canny算法研究及其在图像边缘检测中的应用.pdf还剩51页未读&#xff0c;继续阅读下载文档到电脑&#xff0c;马上远离加班熬夜&#xff01;亲&#xff0c;很抱歉&#xff0c;此页已超出免费预览范围啦&#xff01;如果喜欢就下载吧&#xff0c;价低环保&#xff01;内容要…

flask mysql orm,flask的orm框架(Flask-SQLAlchemy)-创建表

标签&#xff1a;# 转载请留言联系ORM 是什么&#xff1f;ORM&#xff0c;Object-Relation Mapping。意思就是对象-关系映射。ORM 主要实现模型对象到关系数据库数据的映射。优点 :只需要面向对象编程, 不需要面向数据库编写代码.对数据库的操作都转化成对类属性和方法的操作.不…

php+使用go编译,golang如何编译

Go语言中使用 go build 命令主要用于编译代码。在包的编译过程中&#xff0c;若有必要&#xff0c;会同时编译与之相关联的包。go build 有很多种编译方法&#xff0c;如无参数编译、文件列表编译、指定包编译等&#xff0c;使用这些方法都可以输出可执行文件。go build 无参数…

oracle19c监听服务启动失败,Oracle19c安装(有失败成功记录)

Oracle19c安装(有失败成功记录)失败过程失败安装设置 (图为安装成功后获取)成功过程安装设置配置监听桌面类与服务器类的区别总结说明&#xff1a;失败过程失败问题一模一样&#xff0c;无论安装成功或者失败都出现“无法添加用户XXXX到%2%组中”的弹窗&#xff0c;都是点6下继…

linux ospf 命令,OSPF单区域配置 - linuxprobe2020的个人空间 - OSCHINA - 中文开源技术交流社区...

为了弥补距离矢量路由协议的不足&#xff0c;IEFI组织开发了一种基于链路状态的内部网关协议OSPF实验环境&#xff1a;红&#xff0c;绿&#xff0c;蓝三个颜色区域代表三个不同网络的办公场所&#xff0c;要求使用OSPF协议实现网络互通。pc1:172.16.1.1pc2:172.16.2.1pc3:172.…

ubuntu下的linux怎样备份文件,Ubuntu系统如何备份还原?Ubuntu系统备份还原教程

Ubuntu系统如何备份还原&#xff1f;Ubuntu系统是一个以桌面应用为主的开源操作系统&#xff0c;专为开发团队而打造&#xff01;无论你使用的是什么操作系统&#xff0c;都有可能出现电脑无法修复的故障&#xff0c;这时候备份还原功能就显得非常重要了。今天小编要给大家分享…

jenkins linux编译c,【Linux】【Jenkins】代码编译和执行过程中的问题汇总

1.问题1&#xff1a;java.io.FileNotFoundException: /root/.jenkins/workspace/Videoyi_AutoTest_Maven/config-log4j\log4j.xml (No such file or directory)该问题是由于代码是在windows下编写和编译的&#xff0c;使用的都是\\来实现目录结构的&#xff0c;结果到linux下的…

linux清理整个磁盘空间,一次Linux磁盘空间清理的经历

最近&#xff0c;在Linux上运行BPM应用总是报没有空间的错误。经过一番调查和周折&#xff0c;终于找出了问题的症结&#xff0c;并顺利解决。今天&#xff0c;我把过程总结一下&#xff0c;方便自己或其他有类似问题的朋友参考。这里不对具体命令的具体各种参数做深入介绍&…

c语言手游常用代码,c语言源代码【操作流程】

很多小伙伴都遇到过c语言源代码的困惑吧&#xff0c;一些朋友看过网上零散的c语言源代码的处理方法&#xff0c;并没有完完全全明白c语言源代码是如何解决的&#xff0c;今天小编准备了简单的解决办法&#xff0c;只需要按照1&#xff1a;编写C源代码for_learning_compile.c2&a…

pdxp协议 C语言,集成CC控制逻辑,PD协议及MCU的Type-C应用方案

Type-C系列亮点介绍内包MCU、集成CC逻辑和DP协议支持Typec DP Alt mode 和单独的DP输入支持速率最高可达4-lane 5.4Gbps(HBR2)支持macbook2016版本,拔掉adapter不掉电● DP1.2/Type C转HDMI1.4&#xff0c;支持HDCP1.3&#xff0c;可扩展PD,USB3.0接口● 支持1/2/4 lane DP输…

Android打开谷歌应用,谷歌确认 Android 12 新增剪贴板访问提醒,将在 Beta 2 上线

IT之家 5 月 19 日消息 据外媒 xda-developers 报道&#xff0c;近年来&#xff0c;谷歌一直在打击 Android 系统中的剪贴板访问&#xff0c;并在发布 Android 10 时禁止后台应用读取剪贴板数据。在最新的 Android 12 中&#xff0c;谷歌引入了一项设置&#xff0c;每当应用访问…

Android nfc编译,【Android编译】各个模块编译方法

一、如何编译出vendor.img1. 首先找到产品对应BoardConfig.mk路径&#xff1a;LINUX/android/device/项目/产品/BoardConfig.mk2. 修改BoardConfig.mk设置下面代码中的ENABLE_VENDOR_IMAGE为true。#Enable split vendor imageENABLE_VENDOR_IMAGE : true#ENABLE_VENDOR_IMAGE :…

android7.0 蓝牙定位,BluetoothAdapter在Android6.0/7.0+以上startDiscovery不能发现蓝牙设备问题...

BluetoothAdapter在Android6.0以上startDiscovery不能发现蓝牙设备问题问题的重要原因之一是Android 6.0&#xff0c;Android 7.0的权限问题引起的。在Android 4.0上运行良好的蓝牙代码&#xff0c;在高版本运行异常。比如BluetoothAdapter的startDiscovery虽然启动了发现蓝牙任…

19年的华为手机还能搭载鸿蒙吗,2019年华为手机出货或超2.15亿部 鸿蒙系统最快10月首秀...

科客点评&#xff1a;备用方案可以说是越多越好&#xff0c;这样的确能有效避免突发事件所带来的巨大风险。6月13日&#xff0c;知名分析师郭明錤给出了有关华为的最新预测报告&#xff0c;该预测报告主要对华为手机今年的出货量进行了预测。根据分析师郭明錤的报告显示&#x…

html5如何新建定义站点,HTML5技术教程:创建新作品_HTML5教程_创建作品_添加元素_课课家...

我们所熟知的HTM5软件是一款非常强大功能的软件&#xff0c;据我了解HTM5软件的特色也是非常有优势的。我们先来介绍一下它的优势&#xff1a;HTML5可以提供:①&#xff1a;提高可用性和改进用户的友好体验;②&#xff1a;有几个新的标签&#xff0c;这将有主(助?)开发人员定义…

app inventor HTML5,[App Inventor] Web客戶端元件 POST 傳值的使用方式

過去在開發App時&#xff0c;Web客戶端元件大部份都以Get的方式進行值的傳遞。那可以用POST嗎&#xff1f;以下簡單的範例&#xff0c;我們將使用Web客戶端元件以POST的方式傳值給一個PHP程式&#xff0c;然後再返回結果顯示在App中。1. 如下圖我們新增一個專案&#xff0c;在工…

html安卓手机打开后只有半屏,宽度设置100%在移动端时变成一半

html代码&#xff1a;手机电脑DIY数码外设智能css代码&#xff1a;.nav-body{position: relative;overflow: hidden;width:100%;height: 400px;}.nav-img{position: absolute;z-index:-1;}.nav-img a{display: block;width:100%;}.nav-img img{height: 400px;width:100%;min-wi…