Runnable
- interface:它是一个接口
- run():它唯一的方法,一个run需要实现的方法,线程的逻辑写在这里
class RunnableDemo implements Runnable{
@override
public void run(){
//do something...
}
}
public static void main(String[] args){
Thread t = new Thread(new RunnableDemo());
t.start();
}
Thread(单继承方式)
- class:首先它是一个类,它implements Runnable,getName()可以获取它的名字,setName()可以设置它的名字
- run():重写Runnable的方法,它也不实现,只是调用Runnable的run()
- start():the JVM calls the run method of thread.
- sleep():params is millis.
- yeild():the current thread is willing to yeild its current use of processor,the scheduler is free.
- join():wait for this thread to die.
- currentThread():return a reference to the currently executing thread object.
class ThreadDemo extends Thread{
@override
public void run(){
//do something
}
}
public static void main(String[] args){
Thread t = new ThreadDemo();
t.start();
}
Synchronized
synchronized(object){}块实现线程互斥
运用Object的wait/notify/notifyAll方法实现线程同步
synchronized(object){
object.wait();
object.notify();
obejct.notifyALl();
}
wait():the current thread to wait until another thread invokes the notify() method or the notifyAll() for this object.
synchronized也可用于修饰方式,一个被synchronized修饰的方法,保证了线程的安全性,这个方法没被执行完或者没有调用wait方法之前,其他线程都被阻塞,直到方法执行完或者调用wait方法。
volatile
保证了线程可以正确地读取其他线程写入的数据
原因:线程内存可见性,JMM,happens-before原则
注意:volatile只适用于更改数据不依赖于数据本身,比如boolean变量,温度变量等。
Daemon
守护线程
thread.setDaemon(true)
- 在start()之前设置,否则会抛IllegalThreadStateException。
- 在Daemon线程中产生的新线程也是Daemon的。
- 不是所有的应用都可以分配给Daemon线程来进行服务,比如读写操作或者计算逻辑。因为如果没有线程让守护线程守护的话,Daemon Thread还没来的及进行操作时,Daemon Thread可能随着JVM退出了。
Callable、Futrue、ExecutorService、CountDownLatch
实现Callable接口类
public class TestCallable implements Callable<Integer>{
private CountDownLatch countDownLatch;
public TestCallable(CountDownLatch countDownLatch){
this.countDownLatch=countDownLatch;
}
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"run...");
final long numSleep = 10000;
int r = (int)(Math.random()*10);
System.out.println("start sleep "+Math.floor(numSleep/1000)+" seconds...");
Thread.sleep(numSleep);
System.out.println("wake up!");
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName()+"end!");
return r;
}
}
测试方法:
public static void main(String[] args) throws InterruptedException, ExecutionException {
final int numThread = 3;
List<Future<Integer>> futureList = new ArrayList<>();
CountDownLatch countDownLatch = new CountDownLatch(numThread);
// ExecutorService pool = Executors.newCachedThreadPool();
ExecutorService pool = Executors.newFixedThreadPool(numThread);
for(int i=0;i<numThread;i++){
Callable<Integer> c1 = new TestCallable(countDownLatch);
Thread.currentThread().setName("thread-"+i);
futureList.add(pool.submit(c1));
}
pool.shutdown();
countDownLatch.await();
for (Future<Integer> future : futureList) {
if(future.isDone()){
System.out.println(future.get());
}else{
System.out.println("f is running...");
}
}
}
单例模式的多线程问题:
用DCL(双重检测)解决单例模式中的懒汉模式的多线程问题中,为什么需要双层?
volatile保证获取对象来判断对象是否为空的时候,获取的是公共栈中的对象(得到及时更新),asynchronized保证了创建对象的原子性。
为什么用内部类解决单例模式中的懒汉模式的多线程问题中,遇到序列化会创建多个对象?