多线程demo理解

翻书:哦,马冬梅

合书:马什么梅?

翻书:哦,马冬梅?

合书:马东什么?

翻书:哦,马冬梅啊

合书:什么东梅?

多线程,很多人听到就头疼的东西(我听到也头疼)但是还是决定准备写下来加深一下理解吧。

一、啥是多线程

首先,先来一点文邹邹的东西,一个程序是一个进程 ,一个进程至少有一个线程,而线程是操作系统可识别的最小执行和调度单位。而多线程是多个线程并发执行。

eg:如果楼下食堂是一个系统的话,你火急火燎的去吃饭,等待(手抖的)阿姨给你打菜,但是楼下的队伍长的出奇,这让你很不开心让来吃饭的人也都很不开心,于是乎食堂老板含泪多招了几位阿姨来一起给你们打菜。这就可以理解为多条线程并发执行任务。

二、如何创建线程

1.一个类继承Thread类,并重写里面的run()方法。

2.一个类去实现Runnable接口,并实现里面的run()方法。

扫描二维码关注公众号,回复: 8655445 查看本文章

3.创建一个线程池,并线程池中直接获取一个线程。

一般常用的是第二种,因为java只能单继承但是可以多实现

三、代码实例

首先我们设计大家普遍运用的场景:

很前一段时间复联4上映了,那叫一个火啊,其中钢铁侠、美国队长、雷神。。。。差点跑题了。这么火的电影首映当然得靠抢啊,这一天万达影城预售100张票,由三个自助售票机售卖。于是乎我们有了如下代码:

ThreadDemo.java

public class ThreadDemo implements Runnable{
	
	//预售100张
	private int tickets = 100;
	
	@Override
	public void run() {
		while (true) {
			if (tickets > 0) {
				System.out.println(Thread.currentThread().getName() + "正在售卖第" + (tickets--) + "张票");
			}else{
				return;
			}
		}
	}

}

SellTicketDemo.java

public class SellTicketDemo {
	public static void main(String[] args) {
		ThreadDemo demo = new ThreadDemo();
		Thread t1 = new Thread(demo,"售票机1号");
		Thread t2 = new Thread(demo,"售票机2号");
		Thread t3 = new Thread(demo,"售票机3号");
		t1.start();
		t2.start();
		t3.start();
	}
}

执行main结果如图:

好像没什么问题,但是这是在我的测试中,实际生活中由于网络原因肯定会出现一点延迟情况,下面我在run方法中添加一丢丢延迟(加100毫秒,很短的延迟了 )

ThreadDemo.java

public class ThreadDemo implements Runnable{
	
	//预售100张
	private int tickets = 100;
	
	@Override
	public void run() {
		while (true) {
			if (tickets > 0) {
				System.out.println(Thread.currentThread().getName() + "正在售卖第" + (tickets--) + "张票");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}else{
				return;
			}
		}
	}
}

结果:

出现了一票多卖的情况,因为延迟的原因导致线程之间的数据没有及时同步导致的。这个时候就需要引入一个同步机制,也就是synchronized关键字

public class ThreadDemo implements Runnable{
	
	//预售100张
	private int tickets = 100;
	
	@Override
	public void run() {
		while (true) {
			synchronized (this) {
				if (tickets > 0) {
					System.out.println(Thread.currentThread().getName() + "正在售卖第" + (tickets--) + "张票");
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}else{
					return;
				}
			}
		}
	}
}

如图已经正常。但是看起来又不像那么正常,感觉售票机2号好像没工作,其实并不是,因为有很大可能在线程1执行run的时候在while里面执行if,这时已经锁住了,线程2和3无法操作,但是当if执行结束后释放锁,但是紧接着第二波的循环过来了,第二波循环到来的比线程2、3获取的快,就会导致执行结果为某一条线程消耗了所有票,结果可能会误导一些人们,其实事实上程序并没错只是其他获取锁没有循环来的快而导致的。可以在if后加上一个短暂延迟,便于测试与理解。

代码实例:

public class ThreadDemo implements Runnable{
	
	private int tickets = 100;
	

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + "执行run方法");
		while (true) {
			synchronized (this) {
				System.out.println(Thread.currentThread().getName() + "上锁");
				if (tickets > 0) {
					try {
						// 延迟
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "正在消耗第" + (tickets--) + "条数据");
				}else{
					System.out.println(Thread.currentThread().getName() + "没数据了");
					return;
				}
				System.out.println(Thread.currentThread().getName() + "即将解锁");
			}
			try {
				//延迟100毫秒让其他线程进入
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
	}
}
public class SellTicketDemo {
	public static void main(String[] args) {
		ThreadDemo demo = new ThreadDemo();
		Thread t1 = new Thread(demo,"线程1");
		Thread t2 = new Thread(demo,"线程2");
		Thread t3 = new Thread(demo,"线程3");
		t1.start();
		System.out.println("线程1已启动");
		t2.start();
		System.out.println("线程2已启动");
		t3.start();
		System.out.println("线程3已启动");
	}
}

合书:嗯,马冬梅。

发布了20 篇原创文章 · 获赞 58 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/zks_4826/article/details/99547676
今日推荐