标签:Java Thread System 线程 run 资源 out
线程
首先需要了解,什么是线程?
线程不是进程,但其行为很像进程,线程是比进程更小的执行单位,一个进程在其执行的过程中,可以产生多个线程。线程是程序执行的一条路径,一个进程可以包含多条线程。多线程并发执行可以提高程序的效率,可以同时完成多项工作。
线程的生命周期
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请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-0获取资源2执行
Thread-0线程1使用资源1请求资源2
Thread-1线程2使用资源2请求资源1
造成了死锁的现象。
标签:Java,Thread,System,线程,run,资源,out 来源: https://blog.csdn.net/weixin_44298615/article/details/98345313
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。