【java】Thread 学习小结

·Background

一提到线程的概念首先应该想到进程。

简单说来,进程就是正在运行的程序;换句话说进程是系统进行资源分配和调用的独立单位。每个进程都有自己的内存空间和系统资源。

·线程

线程是程序中一个单一的顺序控制流程。线程是进程中的一个实体,是被系统独立调度和分派的基本单位。

·多线程

在单个程序中同时运行多个线程完成不同的工作,称为多线程。

需要注意的一点是,多线程的存在,不是提高程序的执行速度,而是为了提高应用程序的使用率。

·多线程的实现方式

方式一:继承Thread类

1)自定义MyThread类继承Thread类

2)在MyThread类中继承run()方法

3)创建MyThread类的对象

4)使用start()方法启动对象

方式二:实现Runnable接口

1)自定义MyRunnable类实现Runnable接口

2)在MyRunnable类中重写run()方法

3)创建MyRunnable类的对象

4)创建Thread类的对象,并把上一步创建的对象作为构造函数的参数传递过来。

同方式一相比,方式二的优势:

1)可以避免由于java单继承带来的局限性

2)适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效的分离,较好的体现了面向对象的设计思想。

·多线程的安全问题:

需要从以下三个方面去考虑:

1)是否有多线程环境。

2)是否有共享数据

3)是否是多条语句操作共享数据

·线程中的死锁问题

理解:两个或两个以上的线程在执行的过程中争夺资源容易发生死锁的情况。

原因:同步嵌套情况下容易出现。

·线程的生命周期

主要有两种:

1)新建-就绪-运行-死亡

2)新建-就绪-运行-阻塞-就绪-运行-死亡

·常用方法

1)yield()

线程让步也就是暂停当前正在执行的线程对象,并执行指定的线程对象

2)stop()

线程中断。可以设定一定的休息时间,限定时间内无醒不过来就可以直接stop进行线程中断。

3)sleep()

线程休眠。可以设置一定的休息时间。

4)priority()

线程优先级调度。线程默认的优先级为5(优先级范围为:1-10)

5)join()

线程加入。

6)daemon()

守护线程。

7)start()

开启线程。

8)run()

运行线程

当然,还有很多其他的方法也是经常用到的,比如:getThread(),setThread()等。这里就不一一列举啦。


下面是小编模仿做的一个小实例:

1)场景介绍:某电影院目前正在上映的贺岁大片,共有100张票,且它有三个售票窗口,设计一个程序模拟该电影院的售票。

2)实现思路:采用继承Runnable接口的方式实现。代码如下:

---定义sellTicket类---

public class SellTicket implements Runnable{
	//定义100张票(为了让多个线程共享。。)
	private static int tickets=100;
	@Override
	public void run(){

		//是为了模拟一直有票
		while(true){
			if(tickets>0){
				System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"张票");
			}
		}
}

---SellTicketDemo类---

public class SellTicketDemo {
	public static void main(String[] args) {
		
		//创建资源对象
		SellTicket st=new SellTicket();
		//创建三个线程对象
		Thread t1=new Thread(st,"窗口1");
		Thread t2=new Thread(st,"窗口2");
		Thread t3=new Thread(st,"窗口3");
		
		//启动线程
		t1.start();
		t2.start();
		t3.start();
	}
}

3)执行效果:


4)出现的问题:

问题1:相同的票被卖出多次

问题2:出现负数和0票。

5)解决思路

很显然,需要保证线程的安全性。问题就在于最一开始初始化100张票那。100英爱作为多个线程共享的数据。所以需要保证其原子性。另一方面就是需要为线程加锁(设置一定的延迟时间)

且看小编改进后的SellTicket类的代码实现:

public class SellTicket implements Runnable{

	//定义100张票
	private int tickets=100;
	//定义一把锁
	private Object obj=new Object();
	
	@Override
	public void run() {
		while(true){
			synchronized(obj){//发现这里的代码将来是会被锁上的,所以t1进来后,就锁了。
				if(tickets>0){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"张票");
				}
			}
		}
		
	}
	
}

6)实现效果:


这下,就没有重复和负数票的情况啦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 39
    评论
Java多线程是指在一个Java程序中同时执行多个线程,每个线程都是独立的执行流。Java中创建线程的方式有三种:继承Thread类、实现Runnable接口和实现Callable接口。每种方式都有其优缺点。 1. 继承Thread类创建线程类: ```java class MyThread extends Thread { public void run() { // 线程执行的代码 } } // 创建线程对象并启动线程 MyThread thread = new MyThread(); thread.start(); ``` 优点:简单易用,可以直接重写Thread类的run()方法。 缺点:由于Java不支持多继承,继承了Thread类就无法再继承其他类。 2. 实现Runnable接口创建线程类: ```java class MyRunnable implements Runnable { public void run() { // 线程执行的代码 } } // 创建线程对象并启动线程 Thread thread = new Thread(new MyRunnable()); thread.start(); ``` 优点:避免了单继承的限制,可以继续继承其他类或实现其他接口。 缺点:需要额外创建Thread对象,并将Runnable对象作为参数传递给Thread对象。 3. 实现Callable接口创建线程类: ```java class MyCallable implements Callable<Integer> { public Integer call() throws Exception { // 线程执行的代码 return 0; } } // 创建线程池对象 ExecutorService executor = Executors.newFixedThreadPool(1); // 提交Callable任务并获取Future对象 Future<Integer> future = executor.submit(new MyCallable()); // 获取线程执行结果 int result = future.get(); ``` 优点:可以获取线程执行的结果,并且可以抛出异常。 缺点:相对于前两种方式,使用Callable需要更多的代码。
评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值