java多线程笔记

近期重温了一遍张孝祥老师的java多线程学习视频,粗略记录一下学习笔记。

一、多线程的实现

  1. extends Thread (示例略)
  2. implements Runnable
new Thread(new Runnable() {
    @Override
    public void run() {
        while(true){
            outputter.output("zhangxiaoxiang");
        }
 }
}).start();

二、定时任务

new Timer().schedule(new TimerTask(){
    @Override
    public void run() {
        //dosth
    }
},2000);

三、线程同步(synchronized)

1.线程同步

方式一
public synchronized void output2(String name) {}
等同于
public void output2(String name) {
  synchronized (this) {}
}

方式二
public synchronized static void output2(String name) {}
等同于
public void output2(String name) {
  synchronized (XXX.class) {} 
}

2.线程切换(Object.wait(),Object.notify(),Object.notifyAll())必须与synchronized联合使用

boolean subFlag = true; //调用sub信号
synchronized void doSub(int loop) {
    while(!subFlag) {
        wait();
    }
    //dosomething
    subFlag = false;
    notify();
}

synchronized void doMain(int loop) {
    while(subFlag) {
        wait();
    }
    //dosomething
    subFlag = true;
    notify();
}

四、ThreadLoacle

ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.set(11);
threadLocal.get();

五、java.util.current包

(一)AtomicInteger

AtomicInteger atomicInteger = new AtomicInteger(5);
atomicInteger.decrementAndGet(); // 自减
atomicInteger.incrementAndGet();//自增

(二).线程池
1.ThreadPool

ExecutorService threadPool = Executors.newFixedThreadPool(3); //固定的线程池
ExecutorService threadPool = Executors.newCachedThreadPool(); //缓存的线程池
ExecutorService threadPool = Executors.newSingleThreadExecutor(); //单一线程,与Thread的区别是,这里线程死掉时会重新启动一个线程。

//执行多个任务
for (int k = 0 ; k < 10 ; k++) {
    threadPool.execute(new Runnable() {
        @Override
        public void run() {}
    });
}

threadPool.shutdown(); //等待任务结束时,关闭线程池
threadPool.shutdownNow(); //立即关闭线程池, 不等待任务完成;

2.ScheduledThreadPool

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);

scheduledExecutorService .schedule(new Runnable() {
    @Override
    publicvoid run() {}
}, delay, timeunit); //延迟delay后执行(仅执行一次) ,timeunit时间单位

scheduledExecutorService .scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {}
}, delay,period ,timeunit); //延迟delay后执行 ,之后每隔period执行一次,timeunit时间单位

(三).Callable 和 Future
1.方式一


Future<String> future = threadPool.submit(new Callable<String>() {
    @Override
    public String call() throws Exception {return "";}
});
System.out.println("拿到结果:"+future.get()); //阻塞型,等待任务调用结束后,才继续往下执行;

2.方式二

CompletionService completionService = new ExecutorCompletionService(threadPool);
for(int i = 0 ; i < 10 ; i++) {
    completionService.submit(new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {return task;}
    });
}

for(int i = 0 ; i < 10 ; i++) {
    System.out.println("take:"+completionService.take().get()); //依旧是阻塞的,会获取到先结束的task
}

(四).锁
1.Lock

private Lock lock = new ReentrantLock();
public void output(String name) {
    try{
        lock.lock(); //此处作用类似 synchronized
        //dosth
    }finally {
        lock.unlock();
    }
}

2.ReadLock ,WriteLock

private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void get() {
    lock.readLock().lock();
    //querydb
    lock.readLock().unlock();
}

public void put(){
    lock.writeLock().lock();
    //set db
    lock.writeLock().unlock();
}

3.Lock和Condition
Condition(await(),signal()替代synchronized的wait()和notify()作用),必须结合Lock使用

condition.await();
condition.signal();

(五).信号量(Semaphore )

Semaphore semaphore = Semaphore(int permits, boolean fair); //fair=true表示先进入的先调用,否则执行的快的先调用

semaphore.acquire(); //请求信号
semaphore.availablePermits();//获取可用的信号量数
semaphore.release(); //释放信号

(六).其他同步根据(CyclicBarrier + CountDownLatch + Exchanger)
1.CyclicBarrier (cyclic:循环的,barrier:障碍物)
–(总共n个线程) 到任意一个cyclicBarrier后,开始等待,待n个线程全部到达时, 再各自执行各自的线程
–表示大家彼此等待,大家集合好后才出发。比如在旅游的过程中,设置集合点,集合后才能再向下一个集合点出发

CyclicBarrier cb = new CyclicBarrier(5);
cb.await(); //等待,其他的线程执行到此处

cb.getNumberWaiting(); //当前等待的人数,

2.倒计时器 CountDownLatch(latch:门闩)
–ps:可以模拟等待红灯;

CountDownLatch latch = new CountDownLatch(3);
latch.await(); //等待latch 计数为0
//dosomething();//

latch.countDown();// latch计数 -1 
latch.getCount(); //返回当前计时数

3 .Exchanger
–用来实现两个线程的信息交换,先到达的线程等待另外一个线程后,才能彼此交换数据.

Exchanger<String> thingExchanger = new Exchanger();
Obect obj2 = exchanger.exchange(obj1);

(七).阻塞队列(BlockingQueue+ArrayBlockingQueue)
BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(null 或 false,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:
这里写图片描述

(八).同步集合
1.Collections.synchronizedXXX()

Map map = Collections.synchronizedMap(new HashMap<Object, String>());
List list = Collections.synchronizedList(new ArrayList<>());

2.ConcurrentHashMap + CopyOnWriteArrayList

ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap();
CopyOnWriteArrayList copyOnWriteArrayList = new CopyOnWriteArrayList();

猜你喜欢

转载自blog.csdn.net/it_freshman/article/details/79121490