多线程与高并发

进程:一个程序跑起来
线程:一个程序里不同的执行路径 线程间切换发生在内核态
纤程:用户空间之内的线程 一个线程里不同的执行路径 纤程间切换发生在用户态 做内存计算的 短时间内能见到结果的 不需要通过中断 不需要通过内核的适合用纤程 启动时需要加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());
        });
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值