java多线程学习笔记(二)

news/2024/5/20 13:00:43 标签: java, 多线程, 状态, 同步锁, 死锁

本文主要记录了一些本人学习多线程的一下笔记,可作为多线程入门参考。

一、线程简介

请看:https://blog.csdn.net/qq_33157666/article/details/103949005

二、线程状态

线程的状态主要包括:

新建状态(New):新创建了一个线程对象。
就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
             等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
             同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
             其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

2.1 线程休眠_sleep

  • sleep(时间)指定当前线程阻塞的毫秒数(1000=1秒);
  • sleep存在异常InteruptedException;
  • sleep时间达到后线程进入就绪状态
  • sleep可以模拟网络延时、倒计时等;
  • 每一个对象都要一个锁,sleep不会释放锁。
//模拟倒计时
public class TestSleep2{
		
	public static void main(String[] args) {
		try {
			tenDown();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void tenDown() throws InterruptedException{
		int num=10;
		while(true){
			Thread.sleep(1000);
			System.out.println(num--);
			if(num<=0){
				break;
			}
		}
	}
}

运行结果:

2.2 线程礼让_yield

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞;
  • 将线程从运行状态改为就绪状态
  • 让cpu重新调度,礼让不一定成功;
/**
 * 测试礼让线程
 * 礼让不一定成功,看cpu心情
 */
public class TestYield {
	public static void main(String[] args) {
		MyYield myYeild=new MyYield();
		//如果礼让成功,第一个线程执行到一半时,会让给第二个线程,否则等第一个线程执行完再执行第二个线程
		new Thread(myYeild,"a").start();
		new Thread(myYeild,"b").start();
	}
	
}

class MyYield implements Runnable{

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+"线程开始执行");
		Thread.yield();//线程礼让
		System.out.println(Thread.currentThread().getName()+"线程停止执行");
		
	}
}

运行结果:

1、礼让失败

2、礼让成功

 

2.3 线程强制执行_join

  • join可以理解为插队
  • join合并线程,待此线程执行完成后,在执行其他线程,其他线程阻塞
/**
 * 测试join方法
 * 想象为插队
 */
public class TestJoin implements Runnable{

	@Override
	public void run() {
		for (int i = 0; i < 1000; i++) {
			System.out.println("线程vip来了"+i);
		}
	}

	public static void main(String[] args) throws InterruptedException {
		//启动线程
		TestJoin testJoin=new TestJoin();
		Thread thread=new Thread(testJoin);
		thread.start();
		
		//主线程
		for(int i=0;i<500;i++){
			if(i==200){
				thread.join();//插队
			}
			System.out.println("main="+i);
		}
	}
}

运行结果:

可以看到当主线程运行到第200的时候,子线程开始插队执行到结束,主线程才开始执行,所以在开发过程中,要谨慎使用join,因为会影响程序执行效率。

2.4 线程停止

原stop有缺陷,已停止使用,现在分享一种使用修改标志位,让线程停止的方法

/**
 * 使用修改标志位的方式,停止线程
 *
 */
public class TestStop implements Runnable{
	int i=0;
	//标志位,默认为ture,不停止
	Boolean flag=true;
	@Override
	public void run() {
		while (flag) {
			System.out.println("Run Theard"+i++);
			
		}
	}

	//将标志位改为false
	public void stop(){
		flag=false;
	}
	
	public static void main(String[] args) {
		TestStop testStop=new TestStop();
		new Thread(testStop).start();
		
		for (int i = 0; i < 100; i++) {
			System.out.println("main i="+i);
			if(i==90){
				//调用stop方法,修改标志位,让线程停止
				testStop.stop();
				System.out.println("线程该停止了");
			}
		}
	}
}

运行结果如下:

从图片中可以看出,当i=90时,停止了线程,只剩下主线程自己执行

2.5 观察线程的状态

/**
 * 观察测试线程的状态
 *
 */
public class TestState implements Runnable{
	
	public static void main(String[] args) throws InterruptedException {
	
		Thread thread=new Thread(new TestState());
		
		//观察状态
		Thread.State state=thread.getState();
		System.out.println("1---"+state);//NEW
		
		//观察启动后
		thread.start();
		state=thread.getState();
		System.out.println("2--"+state);//Run
		while(state!= Thread.State.TERMINATED){//只要线程不终止,就一直输出状态
			Thread.sleep(100);
			state=thread.getState();//更新线程状态
			System.out.println("3--"+state);//输出状态
		}
	}

	@Override
	public void run() {
		for(int i=0;i<3;i++){
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		System.out.println("");
	}
}

运行结果:

可以看出:线程的状态如下图:

2.6 线程优先级

  • java提供了一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度那个线程来执行;

  • 线程的优先级用数字表示,范围1~10

  • Thread.MIN_PRIORITY=1;

  • Thread.MAX_PRIORITY=10;

  • 使用一下方式改变或者获取优先级:

  • getPriortity()  setPrioritity(int xxx);

  • 注意:优先级低只是意味着或得调度的概率低,并不是优先级低就不会被调用了;优先级高也不一定马上就能获取调度,这都是看cpu的调度;

  • 优先级的设定建议在start()调用前;

  • 默认的优先级是5。

/**
 * 测试优先级
 */
public class TestPriority {
	public static void main(String[] args) {
		//主线程优先级
		System.out.println(Thread.currentThread().getName()+":-->"+Thread.currentThread().getPriority());
	
		MyPriority myPriority=new MyPriority();
		Thread t0=new Thread(myPriority);
		Thread t1=new Thread(myPriority);
		Thread t2=new Thread(myPriority);
		Thread t3=new Thread(myPriority);
		Thread t4=new Thread(myPriority);
		Thread t5=new Thread(myPriority);
		
		t0.start();
		
		//先设置优先级,在启动
		t1.setPriority(1);
		t1.start();
		
		t2.setPriority(4);
		t2.start();
		
		t3.setPriority(Thread.MAX_PRIORITY);//MAX_PRIORITY=10
		t3.start();
		
		t4.setPriority(8);
		t4.start();
		
		t5.setPriority(7);
		t5.start();
	}

}

class MyPriority implements Runnable{

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+":-->"+Thread.currentThread().getPriority());
	}
}

运行结果:

 

三、线程同步

请看:https://blog.csdn.net/qq_33157666/article/details/103949120


http://www.niftyadmin.cn/n/1513697.html

相关文章

java多线程学习笔记(三)

一、线程简介 请看&#xff1a;https://blog.csdn.net/qq_33157666/article/details/103949005 二、线程状态 请看&#xff1a;https://blog.csdn.net/qq_33157666/article/details/103949045 三、线程同步 为什么要进行线程同步&#xff1f; java允许多线程并发控制&#…

java多线程学习笔记(四)

一、线程简介 请看&#xff1a;https://blog.csdn.net/qq_33157666/article/details/103949005 二、线程状态 请看&#xff1a;https://blog.csdn.net/qq_33157666/article/details/103949045 三、线程同步 请看&#xff1a;https://blog.csdn.net/qq_33157666/article/de…

ASP.net下大文件上传的几个问题讨论

我研究这个问题已经很长时间了&#xff0c;ASPUpload的组件以及其它几个组件都使用过&#xff0c;多多少少对这些组件的工作原理有些了解&#xff0c;对于其它一些问题的讨论也都遇到过。前几个星期开发的WebbUpload2.0经过一段时间的测试后&#xff0c;发现它完全是一个超级大…

基于Arduino控制伺服电机(舵机)

一&#xff0c;串口监视器的应用 运用到的函数与关键字有&#xff1a;setup,loop,begin,println,print,available,parselnt. 其中begin&#xff0c;avaliable属于Serial库中的库函数&#xff0c;调用格式为 库函数名.需要调用的函数。 setup:只执行一次&#xff0c;ardu…

求解(暂放.net主页,谢谢支持)

近来一直做p2p直播项目&#xff0c;目前第一个版本已经接近尾声&#xff0c;基本功能也已经基本完成&#xff0c;忽然产品目标的主管要求在视频播放里面加一个广告链接&#xff0c;就是在视频播放的时候&#xff0c;用户点击播放器的视频画面后自动打开IE窗口连接到指定的网站&…

基于arduino的多个舵机控制

一&#xff0c;setup与外部 首先你想使用舵机就需要去调用arduino ide的Servo这个库函数&#xff0c;第二步定义你的舵机名称采用Servo 舵机名称&#xff0c;我这里有4个舵机就定义了四个。 接下来是setup函数的部分&#xff0c;依旧采用舵机名称.attach()&#xff0c;用来告诉…

备战蓝桥杯day1__LED跑马灯

51单片机于大多数单片机不同&#xff0c;在点亮LED时不是仅仅输出一个高电平就可以解决&#xff0c;需要经过一个74HC138译码器&#xff0c;一个74HC573锁存器。 一&#xff0c;74HC138译码器 有6个输入端口但是我们只需要关注A&#xff0c;B&#xff0c;C端口&#xff0c;由…

备战蓝桥杯day2__蜂鸣器与继电器

一&#xff0c;元件介绍 1&#xff0c;继电器 当继电器中间的线圈导通时&#xff0c;电生磁把K1吸下来&#xff0c;与m2连接&#xff0c;不导通时K1与m1连接&#xff0c;当继电器工作时&#xff0c;继电器旁边的LED会亮起。我们通过控制N BELAY端口来控制继电器是否工作&…