class CallableTest implements Callable {
private String name;
public CallableTest(String name) {
this.name = name;
}
@Override
public Integer call() throws Exception {
//当前线程睡一会在执行
Thread.sleep(100);
//返回一个10-100的整数
return (int)(Math.random()*90)+10;
}
public String getName() {
return name;
}
}
线程安全
当多个线程操作同一个共享数据时,当一个线程还未结束时,其他的线程参与进去,此时就会导致共享数据的不一致。
例:
public class ThreadTest {
//初始化线程池,创建方式为指定线程池数量创建
public static ThreadPoolExecutor pool =
new ThreadPoolExecutor(
//核心线程池的数量
5,
//最大线程能开到多少
100,
//线程空闲后,多开的线程多长时间休眠
10,
//线程休眠的时间单位
TimeUnit.SECONDS,
//工作/阻塞队列,一旦核心线程放满后,多余的任务会放进该队列,采用链表阻塞队列
new LinkedBlockingDeque<>(100),
//默认工厂模式
Executors.defaultThreadFactory(),
//阻塞队列满后,采用拒绝策略拒绝服务
new ThreadPoolExecutor.AbortPolicy()
);
public static void main(String[] args) throws InterruptedException, ExecutionException {
CallableTest call = new CallableTest();
Future ft = null;
for (int i = 1; i <= 100; i++) {
ft = pool.submit(call);
}
System.out.println(ft.get());
pool.shutdown();
}
}
class CallableTest implements Callable {
private int num = 0;
@Override
public Integer call() throws Exception {
for (int i = 1; i <= 100; i++) {
num ++;
}
return num;
}
}
结果应该是10000,因为多个线程同时去改变资源,导致数字不是10000,共有2个问题导致数字不对:
-
主线程提前运行,不管子线程是否执行完毕
-
子线程互相争夺资源,导致资源不一致,A线程取出数字,改变数字后想要放进去,但B线程已经拿走了A线程未改变之前的值,A线程改变完后放入,B线程取出改变后放入,这样就看起来是1一个线程改变了值,所以说原本是3,结果确是2,线程多了,资源也就差的越来越多。
改变:
利用synchronized同步代码块
利用synchronized同步方法
利用Lock显示锁
synchronized隐式锁实现线程安全
public class ThreadTest {
//初始化线程池,创建方式为指定线程池数量创建
public static ThreadPoolExecutor pool =
new ThreadPoolExecutor(
//核心线程池的数量
5,
//最大线程能开到多少
100,
//线程空闲后,多开的线程多长时间休眠
10,
//线程休眠的时间单位
TimeUnit.SECONDS,
//工作/阻塞队列,一旦核心线程放满后,多余的任务会放进该队列,采用链表阻塞队列
new LinkedBlockingDeque<>(100),
//默认工厂模式
Executors.defaultThreadFactory(),
//阻塞队列满后,采用拒绝策略拒绝服务
new ThreadPoolExecutor.AbortPolicy()
);
public static void main(String[] args) throws InterruptedException, ExecutionException {
CallableTest call = new CallableTest();
List<Future> fts = new ArrayList<>();
for (int i = 1; i <= 100; i++