线程案例

1 篇文章 0 订阅

举个买火车票的案例

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,也就是说是该对象本身


同步监视器的执行过程:

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

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

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

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


同步的缺点:

死锁:

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

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

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

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



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值