java并发编程的三大特性
<1>.原子性
1、synchronized (互斥锁)
2、Lock(互斥锁)
3、原子类(CAS)
<2>.可见性
<3>.有序性
volatile关键字有两个作用1.保证可见性.2禁止重排序
DCL单例是否需要使用volatile关键字?
单例设计模式
单例代表单个实例,保证一个类的对象永远只有一个!
设计模式
前人遇到问题 总结出来的经验``
饿汉式
优点
简单 多线程下没有任何问题
缺点
当类加载时 对象就会直接创建
如果一直不被使用 对象就白创建了
public class Single {
private static Single s = new Single();
private Single(){
}
public static Single getInstance(){
return s;
}
}
public class Demo01 {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Single.getInstance());
}
}).start();
}
}
}
懒汉式
优点
延迟加载 什么时候调用方法 什么时候创建对象
缺点
多线程 代码有问题
public class Single {
private static Single s ;
private Single(){
}
public static Single getInstance(){
if(s == null){
s = new Single();;
}
return s;
}
}
public class Test {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Single.getInstance());
}
}).start();
}
}
}
DCL双检查锁机制单例(DCL:double checked locking)
DCL单例是否需要使用volatile关键字?
public class Single {
private static /*volatile*/ Single s ;
private Single(){
}
public static Single getInstance(){
if(s == null){
synchronized (Single.class){
if(s == null){
s = new Single();;
}
}
}
return s;
}
}
public class Test {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Single.getInstance());
}
}).start();
}
}
}
DCL单例需要加上volatile关键字,虽然理论上需要,但是实际上这种情况几乎不可能出现.
Callable接口
1.定义实现类 实现Callable接口
2.重写call方法
3.开启线程
创建实现类对象
创建FutureTask对象 传入线程任务
public FutureTask(Callable c);
创建Thread对象 将FutureTask对象 传入
Thread(Runnable r)
FutureTask是Runnable实现类
调用start方法
public class SubCall implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
return 1+1;
}
}
public class Demo01_Callable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
SubCall sc = new SubCall();
FutureTask<Integer> ft = new FutureTask<>(sc);
Thread t = new Thread(ft);
t.start();
System.out.println("....");
//get方法 会等待线程 计算完毕 将结果返回
System.out.println(ft.get());
}
}
今日总结:😁
明日计划:💪