线程安全:
当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法就是线程安全的)
synchronized:
可以在任意对象或方法上加锁,而加锁的这段代码称为“互斥区”或“临界区”
多个线程多个锁:
多个线程都有自己对应的锁
脏读:
在我们对一个对象的方法或对象加锁时,需要考虑业务的整体性,即为setValue/getValue方法同时加锁synchronized同步关键字,保证业务的原子性,不然会出现业务错误(也从侧面保证了数据的一致性)
线程间的通信:
使用notify/wait方法实现线程间的通信(注意这两个方法都是object类的方法)
wait/ notify 必须配合synchronized关键字使用
wait方法释放锁,notify方法不释放锁
CountDownLatch与锁无关
线程的三种实现方式Demo
1 package com.jonychen.test; 2 3 import java.util.concurrent.Callable; 4 import java.util.concurrent.ExecutionException; 5 import java.util.concurrent.FutureTask; 6 7 /** 8 * 线程的三种实现方式 9 */ 10 public class TestDemo { 11 12 public static void main(String[] args){ 13 /** 14 * 第一种方式:继承Thread类重写run()方法 15 */ 16 Thread thread=new ThreadDemo(); 17 thread.start(); 18 19 /** 20 * 第二种方式:实现Runnable接口重写run()方法 21 */ 22 RunnableDemo runnableDemo=new RunnableDemo(); 23 Thread thread1=new Thread(runnableDemo); 24 thread1.start(); 25 try { 26 thread1.sleep(3000); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } 30 31 /** 32 * 第三种方式:实现Callable接口重写call()方法 33 */ 34 CallableDemo callableDemo =new CallableDemo(); 35 FutureTask<Integer> futureTask=new FutureTask<Integer>(callableDemo); 36 Thread thread2=new Thread(futureTask); 37 thread2.start(); 38 try { 39 System.out.println("返回的参数为:"+futureTask.get()); 40 } catch (InterruptedException e) { 41 e.printStackTrace(); 42 } catch (ExecutionException e) { 43 e.printStackTrace(); 44 } 45 } 46 } 47 48 /** 49 * 第一种方式:继承Thread类重写run()方法 50 */ 51 class ThreadDemo extends Thread{ 52 @Override 53 public void run() { 54 System.out.println("我是继承Thread类实现线程的一种方式!"); 55 } 56 } 57 58 /** 59 * 第二种方式:实现Runnable接口重写run()方法 60 */ 61 class RunnableDemo implements Runnable{ 62 @Override 63 public void run() { 64 System.out.println("我是实现Runnable接口实现线程的一种方式"); 65 } 66 } 67 68 /** 69 * 第三种方式:实现Callable接口重写call()方法 70 */ 71 class CallableDemo implements Callable<Integer>{ 72 73 @Override 74 public Integer call(){ 75 return 666666; 76 } 77 }
输出截图:
可替代wait/notify的方法
1 package com.jonychen.test; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.locks.Condition; 6 import java.util.concurrent.locks.Lock; 7 import java.util.concurrent.locks.ReentrantLock; 8 9 /** 10 *java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待, 11 * 其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。 12 * 相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。 13 * 14 * 使用 Lock 来获取一个 Condition 对象。 15 */ 16 public class ConcurrentDemo { 17 18 private Lock lock=new ReentrantLock(); 19 private Condition condition=lock.newCondition(); 20 21 public void before(){ 22 lock.lock(); 23 try { 24 System.out.println("before"); 25 condition.signalAll(); 26 } finally { 27 lock.unlock(); 28 } 29 } 30 31 public void after(){ 32 lock.lock(); 33 try { 34 condition.await(); 35 System.out.println("after"); 36 } catch (InterruptedException e) { 37 e.printStackTrace(); 38 } finally { 39 lock.unlock(); 40 } 41 42 } 43 44 public static void main(String[] args){ 45 46 ExecutorService executorService =Executors.newCachedThreadPool(); 47 ConcurrentDemo concurrentDemo=new ConcurrentDemo(); 48 executorService.execute(()->concurrentDemo.after()); 49 executorService.execute(()->concurrentDemo.before()); 50 } 51 52 }