为什么线程同步
当我们有多个线程要对同一个资源
进行操作的时候,比如说文件,这时候就不能让多个线程同时操作这个文件了。因为当文件共享的时候,多个操作就会产生冲突
。相信使用过git
进行团队开发的人就会有比价深刻的体会。
这时候就需要引入线程的同步
机制。
所谓同步
,是指一个一个执行,也就是排队
,几个线程排队执行,让线程之间有一个先来后到的关系。这样,就不会产生争抢的现象,也就不会出现冲突。
问题描述
一个有两个线程
的程序,第一个线程计算2~1000
之间的偶数及个数,第二个线程计算1000~2000
之间的偶数及个数。
初步实现
首先,我们根据题目来设计一下实现方式。
1.定义两个线程。这里要定义自己的线程类,然后去设置计算偶数的开始和结束
2.实现计算所给范围内的偶数和偶数个数
3.执行线程
可以看到实现方式很简单。初步实现如下:
1.定义自己的线程类:
public class MyTread extends Thread {
private int begin; // 范围开始
private int end; // 范围结束
public MyTread(int begin, int end) {
this.begin = begin;
this.end = end;
}
}
2.实现计算偶数以及偶数个数
@Override
public void run() {
this.getEven(begin, end);
}
// 获取偶数以及个数
private void getEven(int begin, int end) {
int count = 0;
System.out.println(begin + "~" + end + "之间的偶数为:");
if (begin % 2 != 0) {
begin += 1;
}
for (; begin <= end; begin += 2) {
System.out.print(begin + " ");
count++;
}
System.out.println();
System.out.println("偶数个数为:" + count);
}
3.初始化线程,运行
public static void main(String[] args) {
MyTread tread1 = new MyTread(2, 500);
MyTread tread2 = new MyTread(500, 1000);
tread1.start();
tread2.start();
}
注:这里为了展示后面的效果,所以将数字范围减小。
看一下结果:
好像并不是我们想要的效果。我们想要这样的效果:
我们想要每一部分的偶数和偶数个数都在一起,但是我们实现后的效果确实两部分混乱出现的。
程序完善
要解决上面出现的问题,就要用到我们最开始说的线程同步
了。
根据我们开始的介绍,发现实现同步的一个条件就是有一个共享的资源
。那么我们的代码里什么是这个共享的资源
呢?貌似没有。所以先创建一个。
1.建立共享资源
我们这里的共享资源完全就可以是同一个对象
,所以我们就另外建立一个类,用来示例共享资源。
public class Even {}
2.然后在共享类中建立计算偶数的方法:
public class Even {
/**
* 获取某个范围内偶数以及个数
* @param begin 统计开始
* @param end 统计结束
*/
public synchronized void getEven(int begin, int end) {
int count = 0;
System.out.println(begin + "~" + end + "之间的偶数为:");
if (begin % 2 != 0) {
begin += 1;
}
for (; begin <= end; begin += 2) {
System.out.print(begin + " ");
count++;
}
System.out.println();
System.out.println("偶数个数为:" + count);
}
}
细心的人会发现,这个方法跟我们最开始写的方法有点不同,它多了一个关键字:synchronized
。通过这个关键字,我们就能在执行方法的时候,实现线程同步了。
3.最后在线程中调用共享方法
public class MyTread extends Thread {
Even even;
@Override
public void run() {
even.getEven(begin, end);
}
}
这时候,我们再来执行一下:
实现了我们想要的效果。
最后,附上完整代码:
/**
* 偶数类
*/
public class Even {
/**
* 获取某个范围内偶数以及个数
* @param begin 统计开始
* @param end 统计结束
*/
public synchronized void getEven(int begin, int end) {
int count = 0;
System.out.println(begin + "~" + end + "之间的偶数为:");
if (begin % 2 != 0) {
begin += 1;
}
for (; begin <= end; begin += 2) {
System.out.print(begin + " ");
count++;
}
System.out.println();
System.out.println("偶数个数为:" + count);
}
}
public class MyTread extends Thread {
Even even;
private int begin; // 范围开始
private int end; // 范围结束
public MyTread(Even even, int begin, int end) {
this.even = even;
this.begin = begin;
this.end = end;
}
@Override
public void run() {
even.getEven(begin, end);
}
public static void main(String[] args) {
Even even = new Even();
MyTread tread1 = new MyTread(even, 2, 500);
MyTread tread2 = new MyTread(even, 500, 1000);
tread1.start();
tread2.start();
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。