欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

线程案例

程序员文章站 2022-05-02 10:02:07
...

举个买火车票的案例

package com.wbs.Thread;

public class Tickets implements Runnable {
	int tickets=10;//票数
	@Override
	public void run() {
		//5人买票
		for (int i = 0; i < 5; i++) {
			if(tickets>0){
				System.out.println("线程"+Thread.currentThread().getName()+"买票     剩余票数"+(tickets--));
			}
		}
	}
	public static void main(String[] args) {
		Tickets th=new Tickets();
		Thread th1=new Thread(th);
		Thread th2=new Thread(th);
		Thread th3=new Thread(th);
		th1.start();
		th2.start();
		th3.start();
	}

}

线程案例线程案例

每次运行的结果不一样。

分析:

线程有5种状态


新建状态:通过 new 新创建了一个线程对象。

就绪状态:线程对象创建后,调用了该对象的 start() 方法。

                    变得可运行,等待获取 CPU 的使用权。

运行状态:就绪状态的线程获取了CPU,执行程序代码。

阻塞状态:阻塞状态是线程因为某种原因放弃 CPU 使用权,暂时停止运行。

                    直到线程进入就绪状态,才有机会转到运行状态。

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


package com.wbs.Thread;

public class Test implements Runnable {

	@Override
	public void run() {
		
	}
	public static void main(String[] args) {
		Test test=new Test();
		Thread th=new Thread(test);
		System.out.println("线程启动前"+th.isAlive());
		th.start();
		System.out.println("线程 启 动 后"+th.isAlive());
		System.out.println("线程 的 名 字"+Thread.currentThread().getName());
		System.out.println("线程的 优 先级"+Thread.currentThread().getPriority());//优先级
		System.out.println("线程的最大优先级"+Thread.MAX_PRIORITY);//最大优先级
		System.out.println("线程的最小优先级"+Thread.MIN_PRIORITY);//最小优先级
		System.out.println("线程的默认优先级"+Thread.NORM_PRIORITY);//默认优先级
		th.setPriority(2);//设置优先级
		System.out.println(th.getPriority());
	}

}

线程案例


Java 线程的优先级用整数表示,取值范围是1~10。

Thread 类有以下三个静态常量:

static int MAX_PRIORITY

线程可以具有的最高优先级,取值为10。

static int MIN_PRIORITY

线程可以具有的最低优先级,取值为1。

static int NORM_PRIORITY

分配给线程的默认优先级,取值为5。

 setPriority() 和 getPriority() 方法分别用来设置和获取线程的优先级

join()

在当前线程中调用另一个线程的 join() 方法

则当前线程转入阻塞状态

直到另一个进程运行结束

当前线程再由阻塞转为就绪状态。


package com.wbs.Thread;

public class JoinThread implements Runnable {
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName());
			
	}
	public static void main(String[] args) throws InterruptedException {
		JoinThread th=new JoinThread();
		Thread t=new Thread(th);
		t.start();
		for(int i=0 ;i<5;i++){
			if(i==3){
				t.join();
				System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>");
				System.out.println(Thread.currentThread().getName()+">>>>>>>>"+i);
				System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>");
			}
			System.out.println(Thread.currentThread().getName()+">>>>>>>>"+i);
			
		}
	}
}
sleep()

                                                                              

让线程休眠

进入阻塞状态当睡眠结束后

就转为就绪状态

                                                                                      

睡眠类:

package com.wbs.Thread;

public class Sleep implements Runnable{
	@Override
	public void run() {
		System.out.println("进入run方法");
		try {
			Thread.sleep(3000);
			System.out.println("线程睡眠结束");
		} catch (InterruptedException e) {
			System.out.println("线程睡眠被中断");
			return;
		}
		System.out.println("run方法正常结束");
	}
}

测试:

th.interrupt();//中断线程线程案例线程案例

interrupt();//中断线程

 yield()


Thread 类中提供了一种礼让方法  使用 yield() 方法表示  暂停当前正在执行的线程对象  把执行机会让给相同或者更高优先级的线程  但是  实际中无法保证 yield() 达到让步的目的  就好像我们在做公交车的时候  总会有声音提示“请给...让座”  但是实际上是什么情况就无法保证了

package com.wbs.Thread;

public class TestYield implements Runnable {

	@Override
	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println(Thread.currentThread().getName()+">>>>>>>>"+i);
		}
	}
	public static void main(String[] args) {
		TestYield th=new TestYield();
		Thread t= new Thread(th);
		t.start();
		for (int i = 0; i < 10; i++) {
			if(i==5) {
				Thread.yield();//当前正在执行的线程礼让一次
				//System.out.println(">>>>>>>>>>>>>>>>>>>>>>");
			}
				System.out.println(Thread.currentThread().getName()+">>>>>"+i);
		}
	}
	

}

线程案例


线程安全还是举买车票的例子吧!


我们在等待的时候会有延迟。可能会有其他线程抢占资源。导致数据出现错误

线程执行原理:

线程执行还没有执行完毕时,被其他线程抢占资源 ,再回到本线程上,再上一次线程执行的基础上对程序继续执行 

就好像我们利用迅雷下载东西的时候   下载的东西多了   会排队

有些资源就会插队

等插队的资源下载完了

原来的资源继续下载



线程案例

这个买票的程序出错了,原因是线程不同步的。

解决方法:

同步代码块:

可以指定对象(同步就是我一段代码执行完毕,我没执行完别人不能动)

使用 synchronized 关键字对代码块进行修饰

对共享资源上锁,锁的是共享资源的对象


package com.wbs.Thread;

public class Tickets2 implements Runnable {
	int tickets=10;//票数
	@Override
	public void run() {
		//5人买票
		for (int i = 0; i < 5; i++) {
			synchronized(this){
				
				if(tickets>0){
					System.out.println("线程"+Thread.currentThread().getName()+"买票     剩余票数"+(tickets--));
				}
			}
		}
	}
	public static void main(String[] args) {
		Tickets2 th=new Tickets2();
		Thread th1=new Thread(th);
		Thread th2=new Thread(th);
		Thread th3=new Thread(th);
		th1.start();
		th2.start();
		th3.start();
	}

}

同步方法:

(监视的对象只能是this)

在方法上加synchronized关键字

在方法上加锁,锁的依旧是对象

package com.wbs.Thread;

public class Tickets3 implements Runnable {
	int tickets=10;//票数
	@Override
	public void run() {
		//5人买票
		for (int i = 0; i < 5; i++) {
			show();
		}
	}
	public synchronized void show(){
		if(tickets>0){
			System.out.println("线程"+Thread.currentThread().getName()+"买票     剩余票数"+(tickets--));
		}
	}
	       
	public static void main(String[] args) {
		Tickets3 th=new Tickets3();
		Thread th1=new Thread(th);
		Thread th2=new Thread(th);
		Thread th3=new Thread(th);
		th1.start();
		th2.start();
		th3.start();
	}

}

线程同步总结:

同步监视器:

synchronized(obj){}中obj成为同步监视器

同步代码块中同步监视器可以是任何对象

但是推荐使用共享资源作为同步监视器

同步方法中无需指定同步监视器

因为同步方法的监视器是this,也就是说是该对象本身


同步监视器的执行过程:

第一个线程访问,锁定同步监视器,执行其代码

第二个线程访问,发现同步监视器被锁定了,无法访问

第一个线程访问完毕,解除同步监视器

第二个线程访问,发现同步监视器未锁,锁定并访问


同步的缺点:

死锁:

同步可以保证资源共享操作的正确性

但是过多的同步也会产生死锁

当双方都在等待对方资源的时候

程序就进入了阻塞状态,无法执行



相关标签: 线程