进程:一个程序跑起来
线程:一个程序里不同的执行路径 线程间切换发生在内核态
纤程:用户空间之内的线程 一个线程里不同的执行路径 纤程间切换发生在用户态 做内存计算的 短时间内能见到结果的 不需要通过中断 不需要通过内核的适合用纤程 启动时需要加VM参数 -javaagent
线程和纤程的区别
线程重 纤程轻
线程发生在内核空间 纤程发生在用户空间
纤程启动的数量要比线程多的多
为什么用纤程
切换时更简短轻松
Intel的CPU分为四个指令集
ring0-1-2-3,自己的应用程序跑在ring3级,Linux内核跑在ring0级,ring0级可以直接访问硬件
ring3级用户态到ring0级内核态需要经过80中断调用
缓存行的大小是64bytes(字节),一个long型的变量是8个字节,多线程计算大量数据时可以在变量前后分别加7个long型变量,这样每个线程的变量就占一行,不用互相通知和同步,所以效率会变高。Disruptor也是这个原理。JDK1.8提供了@Contended注解也是此功能,注意运行时需要加-XX:-RestrictContended,别的版本不起作用
IntelCPU的缓存一致性协议有MESI
CAS是轻量级锁
volatile特点:可见性 禁止指令重排
volatile 最终实现:lock addl
wait和notify/notifyall
t1.wait→t2.notify:t2 notity了t1之后,t1并不会继续执行,因为notify不释放锁,t1线程仍然拿不到锁
t1.wait→t2.notify→t2.wait:t2.wait释放锁,t1拿到锁继续执行,但是执行结束后t2还结束不了,因为在一直wait
t1.wait→t2.notify→t2.wait→t1.notify
ReentrantLock
Lock lock = new ReentrantLock();
/*synchronized*/ void m1() {
try {
lock.lock();
for (int i = 0; i < 3; i++) {
TimeUnit.SECONDS.sleep(1);
System.out.println("m1_" + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
void m2() {
boolean locked = false;
try {
locked = lock.tryLock(5, TimeUnit.SECONDS);
System.out.println("m2 " + locked);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (locked)
lock.unlock();
}
}
Thread t2 = new Thread(()->{
try {
lock.lockInterruptibly();//可以打断的等待
System.out.println("t2 start");
TimeUnit.SECONDS.sleep(5);
System.out.println("t2 end");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
});
t2.start();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.interrupt();//结束t2的等待
1.trylock:使用tryLock进行尝试锁定,不管锁定与否都继续执行,可以根据tryLock的返回值判定是否锁定,也可以指定tryLock的时间
2.lockinterupptibly:synchronized的时候使用wait,必须别的线程notify才能醒来,lockInterupptibly是可以打断的等待,使用interrupt结束等待
3.reentranlock有公平锁和非公平锁(Lock lock = new ReentrantLock(true);//true的时候为公平锁,默认为非公平锁)
CountDownLatch
倒数计数
Thread[] threads = new Thread[100];
CountDownLatch latch = new CountDownLatch(threads.length);// 100个线程,上个100个线程的门闩
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(()->{
System.out.println(Thread.currentThread().getName());
latch.countDown();// 执行完一个线程就减掉1个线程
});
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
try {
latch.await();// 减到0的时候,门闩打开
} catch (InterruptedException e) {
e.printStackTrace();
}
CyclicBarrier
栅栏
CyclicBarrier barrier = new CyclicBarrier(20, ()->{System.out.println("manren");});// 20个一个栅栏
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "start");
try {
barrier.await();// 满20个放行
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "end");
}).start();
}
Phaser
阶段锁
ReadWriteLock
读锁是共享锁
写锁是排他锁(也叫互斥锁)
static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
static Lock readLock = readWriteLock.readLock();// 读的时候其他读线程可以继续读
static Lock writeLock = readWriteLock.writeLock();// 写的时候其他线程不可以读写
static void read(Lock lock) {
try {
lock.lock();
Thread.sleep(1000);
System.out.println("read");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
static void write(Lock lock, int v) {
try {
lock.lock();
Thread.sleep(1000);
value = v;
System.out.println("write" + v);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
for (int i = 0; i < 18; i++) {
new Thread(()->read(readLock)).start();
}
for (int i = 0; i < 2; i++) {
new Thread(()->write(writeLock, 5)).start();
}
}
Semaphore
可以用来限流
Semaphore semaphore = new Semaphore(1);// 同时允许1个线程运行
//Semaphore semaphore = new Semaphore(2, true);
public static void main(String[] args) {
new Thread(()->{
try {
semaphore.acquire();// 获得许可,1→0,别的线程运行不了
System.out.println("t1 running...");
Thread.sleep(500);
System.out.println("t1 running...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();// 释放许可,0→1,别的线程可以运行
}
}).start();
new Thread(()->{
try {
semaphore.acquire();
System.out.println("t2 running...");
Thread.sleep(200);
System.out.println("t2 running...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}).start();
}
Exchanger
交换
static Exchanger exchanger = new Exchanger();
public static void main(String[] args) {
new Thread(()->{
String s = "T1";
try {
s = (String) exchanger.exchange(s);// 阻塞的方法
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + s);
}, "t1").start();
new Thread(()->{
String s = "T2";
try {
s = (String) exchanger.exchange(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + s);
}, "t2").start();
}
打印输出:
t1 T2
t2 T1
LockSupport
让当前线程阻塞,原来需要加锁然后wait/await,现在不需要加锁想停就可以停
叫醒线程,原来需要notify,所有等待线程都放在等待队列,需要叫醒指定线程非常费劲,现在LockSupport.unpark(t)就可以
可以在park之前调用unpark,而原来不可以在wait之前调用notify。如果先unppark了,在part是停不住的
Thread t = new Thread(
()->{
for (int i = 0; i < 10; i++) {
System.out.println(i);
if (i == 5) {
LockSupport.park();// i==5的时候线程停住
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
);
t.start();
try {
TimeUnit.SECONDS.sleep(8);
System.out.println("after 8s....");
} catch (InterruptedException e) {
e.printStackTrace();
}
LockSupport.unpark(t);//叫醒t线程
写一个固定容量同步容器,拥有put和get,能够支持2个生产者线程和10个消费者线程的阻塞调用
public class T17<T> {
final private LinkedList<T> lists = new LinkedList<>();
final private int MAX = 10; //最多10个元素
synchronized void put(T t) {
while(lists.size() == MAX) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lists.add(t);
this.notifyAll();
}
synchronized T get() {
while (lists.size() == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
T t = lists.removeFirst();
this.notifyAll();
return t;
}
public static void main(String[] args) {
T17<String> t = new T17();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for(int j=0; j<5; j++) System.out.println(t.get());
}).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 2; i++) {
new Thread(()->{
for (int j = 0; j < 25; j++) {
t.put(Thread.currentThread().getName() + " " + j);
}
}).start();
}
}
}
public class T19<T> {
final private LinkedList<T> lists = new LinkedList<>();
final private int MAX = 10; //最多10个元素
Lock lock = new ReentrantLock();
Condition consumer = lock.newCondition();
Condition provider = lock.newCondition();
public void put(T t) {
try {
lock.lock();
while(lists.size() == MAX) { //想想为什么用while而不是用if?
provider.await(); //effective java
}
lists.add(t);
consumer.signalAll(); //通知消费者线程进行消费
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public T get() {
T t = null;
try {
lock.lock();
while(lists.size() == 0) {
consumer.await();
}
t = lists.removeFirst();
provider.signalAll();; //通知生产者进行生产
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return t;
}
public static void main(String[] args) {
T19<String> c = new T19<>();
//启动消费者线程
for(int i=0; i<10; i++) {
new Thread(()->{
for(int j=0; j<5; j++) System.out.println(c.get());
}, "c" + i).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
//启动生产者线程
for(int i=0; i<2; i++) {
new Thread(()->{
for(int j=0; j<25; j++) c.put(Thread.currentThread().getName() + " " + j);
}, "p" + i).start();
}
}
}
BlockingQueue
public static void main(String[] args) {
// Queue<String> q = new ConcurrentLinkedQueue<>();
// for (int i = 0; i < 10; i++) {
// q.offer("a" + i);//相当于list的add,有返回值
// }
// q.poll();//取,并remove
// q.peek();//取,不remove
BlockingQueue<String> q = new LinkedBlockingQueue<>();
Random r = new Random();
new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
q.put("a" + i);//如果满了,就会阻塞
TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "p1").start();
for (int i = 0; i < 5; i++) {
new Thread(()->{
for (;;) {
try {
System.out.println(Thread.currentThread().getName() + "take -" + q.take());//如果没了就会阻塞
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "c"+i).start();
}
}
PriorityQueque
public static void main(String[] args) {
PriorityQueue<String> q = new PriorityQueue<>();
q.add("c");
q.add("e");
q.add("a");
q.add("d");
q.add("z");
for (int i = 0; i < 5; i++) {
System.out.println(q.poll());//按大小输出
}
}
DelayQueue
按时间进行任务调度,用PriorityQueue实现的
static BlockingQueue<MyTask> tasks = new DelayQueue<>();
static Random r = new Random();
static class MyTask implements Delayed {
String name;
long runningTime;
MyTask(String name, long rt) {
this.name = name;
this.runningTime = rt;
}
@Override
public int compareTo(Delayed o) {
if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS))
return -1;
else if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS))
return 1;
else
return 0;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(runningTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public String toString() {
return name + " " + runningTime;
}
}
public static void main(String[] args) throws InterruptedException {
long now = System.currentTimeMillis();
MyTask t1 = new MyTask("t1", now + 1000);
MyTask t2 = new MyTask("t2", now + 2000);
MyTask t3 = new MyTask("t3", now + 1500);
MyTask t4 = new MyTask("t4", now + 2500);
MyTask t5 = new MyTask("t5", now + 500);
tasks.put(t1);
tasks.put(t2);
tasks.put(t3);
tasks.put(t4);
tasks.put(t5);
System.out.println(tasks);
for(int i=0; i<5; i++) {
System.out.println(tasks.take());//按时间优先度输出
}
}
SynchronusQueue
容量为0,给别的线程下达任务用,跟Exchanger概念一样
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> strs = new SynchronousQueue<>();
new Thread(()->{
try {
System.out.println(strs.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
strs.put("aaa"); //没有take的话阻塞
//strs.put("bbb");
//strs.add("aaa");不能add,会报异常
System.out.println(strs.size());
}
TransferQueue
public static void main(String[] args) throws InterruptedException {
TransferQueue<String> strs = new LinkedTransferQueue<>();
new Thread(() -> {
try {
System.out.println(strs.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
strs.transfer("aaa");//take需要先执行
//strs.put("aaa");//take可以在后面
/*new Thread(() -> {
try {
System.out.println(strs.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();*/
}
要求用线程顺序打印A1B2C3…Z26
private static Thread t1;
private static Thread t2;
public static void main(String[] args) {
char[] aI = "ABCDEFG".toCharArray();
char[] aC = "1234567".toCharArray();
t1 = new Thread(()->{
for (char c : aI) {
System.out.print(c);
LockSupport.unpark(t2);
LockSupport.park();
}
}, "t1");
t2 = new Thread(()->{
for (char c : aC) {
LockSupport.park();
System.out.print(c);
LockSupport.unpark(t1);
}
});
t1.start();
t2.start();
}
private static Thread t1;
private static Thread t2;
public static void main(String[] args) {
char[] aI = "ABCDEFG".toCharArray();
char[] aC = "1234567".toCharArray();
final Object o = new Object();
t1 = new Thread(()->{
synchronized (o) {
for (char c : aI) {
System.out.print(c);
try {
o.notify();
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t1");
t2 = new Thread(()->{
synchronized (o) {
for (char c : aC) {
System.out.print(c);
try {
o.notify();
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t2");
t2.start();
t1.start();
}
Callable和Future用法
Callable返回的结果存放在Future中
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("start");
Callable<String> c = new Callable(){
@Override
public String call() throws Exception {
System.out.println("do it....");
TimeUnit.MILLISECONDS.sleep(5000);
return "hello";
}
};
ExecutorService es = Executors.newCachedThreadPool();
Future<String> result = es.submit(c);//异步
System.out.println(result.get());//阻塞
System.out.println("get...");
es.shutdown();
}
start
do it...
5秒后
hello
get...
FutureTask
既是一个Future又是一个Callable
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("start");
FutureTask<String> fs = new FutureTask<>(() -> {
System.out.println("do it....");
TimeUnit.MILLISECONDS.sleep(5000);
return "hello";
});
new Thread(fs).start();
System.out.println(fs.get());
System.out.println("get...");
}
同上
CompletableFuture
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start, end;
/*start = System.currentTimeMillis();
priceOfTM();
priceOfTB();
priceOfJD();
end = System.currentTimeMillis();
System.out.println("use serial method call! " + (end - start));//顺序执行*/
start = System.currentTimeMillis();
CompletableFuture<Double> futureTM = CompletableFuture.supplyAsync(()->priceOfTM());
CompletableFuture<Double> futureTB = CompletableFuture.supplyAsync(()->priceOfTB());
CompletableFuture<Double> futureJD = CompletableFuture.supplyAsync(()->priceOfJD());
//异步执行 三个同时执行 快一些
CompletableFuture.allOf(futureTM, futureTB, futureJD).join();
end = System.currentTimeMillis();
System.out.println("use completable future! " + (end - start));
}
newSingleThreadExecutor
public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int j = i;
service.execute(()->{
System.out.println(j + " " + Thread.currentThread().getName());
});
}
}