打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Java之线程

线程
首先需要了解,什么是线程?
线程不是进程,但其行为很像进程,线程是比进程更小的执行单位,一个进程在其执行的过程中,可以产生多个线程。线程是程序执行的一条路径,一个进程可以包含多条线程。多线程并发执行可以提高程序的效率,可以同时完成多项工作。

线程的生命周期
1、新建:新创建一个线程对象。
2、可运行:线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获得cpu的使用权。
3、运行:可运行状态的线程获得了cpu时间片(timeslice),执行程序代码。
4、阻塞:阻塞状态是指线程因为某种原因放弃了cpu的使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行状态,才有机会再次获得cpu timeslice转到运行状态。阻塞的情况分为三种:等待阻塞、同步阻塞、其他阻塞。
5、死亡:线程run()、main()方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次重生。

多线程并行和并发的区别
多线程并发可以提高程序的效率,那么并行和并发的区别是什么?
并行是两个任务同时运行,在A任务执行的同时,B任务也在执行(需要多核CPU)。
并发是指多个任务都请求运行,而处理器只能接受一个任务,把多个任务安排轮流执行,由于时间间隔较短,让人感觉多个任务在同时运行。

实现多线程的两种方法
一、继承Thread:定义类继承Thread;重写run方法;把新线程做的事写在run()方法中;创建线程对象;开启新线程,自动执行run()方法。

package com.hpu.edu.dong;public class dong {	public static void main(String[] args) throws Exception {		// TODO Auto-generated method stub		MyThread mt=new MyThread();		mt.start();     		for (int i = 0; i < 10; i  ) {			System.out.println("2");		}	}}class MyThread extends Thread{//继承Thread	@Override				public void run() {			//重写run方法		// TODO Auto-generated method stub		for (int i = 0; i < 5; i  ) {			System.out.println("1");		}	}}

二、实现Runnable接口
定义类实现Runnable接口;实现run方法;把新线程做的事写在run方法中;创建自定义的Runnable的子类对象;创建Thread对象,传入Runnable;调用start()开启新线程,内部会自动调用Runnable的run()方法。

package com.hpu.edu.dong;public class dong {	public static void main(String[] args){		// TODO Auto-generated method stub		MyRunnable mr=new MyRunnable();//创建Runnable的子类对象		Thread t=new Thread(mr);		//将其当作参数传递给Thread的构造函数		t.start();						//开启线程		for (int i = 0; i < 8; i  ) {			System.out.println("2");		}	}}class MyRunnable implements Runnable{//定义一个类实现Runnable	@Override	public void run() {//重写run方法		// TODO Auto-generated method stub		for (int i = 0; i < 5; i  ) {//写入要执行的代码			System.out.println("1");		}	}	}

两种方法的区别
区别:
继承Thread:由于子类重写了Thread类的run(),当调用start()时,直接找子类的run()方法。
实现Runnable:构造函数中传入了Runnable的引用,start()调用run()方法时内部判断成员变量Runnable()的引用是否为空,不为空编译时看的是Runnable()的run(),运行时执行的是子类的run()方法。
继承Thread:
好处:可以直接使用Thread类中的方法,代码简单;
弊端:如果已经有了父类,就不能使用这种方法。
实现Runnable接口
好处:定义的线程有父类也没影响,因为有了父类也可以实现接口,而且接口是多实现的。
弊端:不能直接使用Thread中的方法,需要先获取到线程对象后,才能得到Thread的方法,代码复杂。

同步代码块
首先先了解什么是同步?假设有两段代码块,在同一时间只能执行一段,在这段代码块没执行结束之前,不会执行另外一段代码块。
什么情况下需要同步?当多线程并发,有多段代码同时执行时,我们希望某一段代码执行的过程中cpu不要切换到其他线程工作,这时就需要同步。
同步代码块的使用需要用到关键字:synchronized。

package com.hpu.edu.dong;public class dong {	public static void main(String[] args){		// TODO Auto-generated method stub		final weapon wp=new weapon();		new Thread(){			public void run() {				while(true){					wp.print1();				}			}		}.start();		new Thread(){			public void run() {				while(true){					wp.print2();				}			}		}.start();	}}class weapon{	syn s=new syn();	public void print1(){		synchronized (s) {			System.out.print("圣");			System.out.print("耀");			System.out.print("救");			System.out.print("赎");			System.out.print("\r\n");		}	}	public void print2(){		synchronized(s){			System.out.print("苍");			System.out.print("穹");			System.out.print("幕");			System.out.print("落");			System.out.print("\r\n");		}			}}class syn{	}

死锁
死锁定义:多个进程在执行的过程中,因争夺同类资源且资源分配不当而造成的一中互相等待的现象。若无外力作用,它们都将永远无法继续执行,这种状态称为死锁,这些处于等待状态的进程称为死锁进程。
死锁出现的条件:一、必须是两个或者两个以上进程(线程);二、必须有竞争资源。
例子:假设线程1在执行的时候占用了资源1,此时,需要占用资源2才能继续执行,同时线程2使用了资源2,需要占用资源1才能继续执行:

package com.hpu.edu.dong;public class dong1 {		private static String s1="线程1";	private static String s2="线程2";	private static String R1="资源1";	private static String R2="资源2";	public static void main(String[] args) {		// TODO Auto-generated method stub		new Thread(){			@Override			public void run() {				// TODO Auto-generated method stub									while(true){						synchronized (s1) {							System.out.println(getName() s1 "使用" R1 "请求" R2);							synchronized(s2){								System.out.println(getName() "获取" R2 "执行");							}					}				}			}		}.start();		new Thread(){			@Override			public void run() {				// TODO Auto-generated method stub									while(true){						synchronized (s2) {							System.out.println(getName() s2 "使用" R2 "请求" R1);							synchronized(s1){								System.out.println(getName() "获取" R1 "执行");							}					}				}			}		}.start();	}}

运行结果:

Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-0获取资源2执行Thread-0线程1使用资源1请求资源2Thread-1线程2使用资源2请求资源1

造成了死锁的现象。

来源:https://www.icode9.com/content-1-376851.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
对java中的线程感想
并发编程可能存在的问题
java中多线程产生死锁的原因以及解决意见
[高并发]Java高并发编程系列开山篇
一道关于java线程的面试题
Java实现定时任务的三种方法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服