本文共 4779 字,大约阅读时间需要 15 分钟。
使用普通的Set时可能存在不安全性,需要采取额外措施确保线程安全。常见的解决方法包括:
Setset = Collections.synchronizedSet(new HashSet<>());// 或者Set set = new CopyOnWriteArraySet<>();
HashSet内部实际上使用HashMap来存储元素。其主要方法包括:
public boolean add(E e) { return map.put(e, PRESENT) == null;} 这里的PRESENT是一个固定常量,用于表示元素已存在。
Map的基本操作虽然简单,但在多线程环境下可能引发ConcurrentModificationException,需要谨慎使用。
Callable类提供了与Runnable类似的方法,但可以有返回值和抛出异常。主要方法包括:
public interface Callable{ V call() throws Exception;}
与Runnable不同,Callable可以通过FutureTask等类来执行,并可以有返回值。例如:
FutureTaskfutureTask = new FutureTask<>(new MyThread());new Thread(futureTask, "A").start();Integer result = futureTask.get();
CountDownLatch是一个计数器,用于等待一组任务完成。常见用法包括:
CountDownLatch countDownLatch = new CountDownLatch(6);for (int i = 1; i <= 6; i++) { new Thread(() -> { System.out.println(Thread.currentThread().getName() + "Go out"); countDownLatch.countDown(); }, String.valueOf(i)).start();}countDownLatch.await();System.out.println("Close Door"); CountDownLatch的核心原理是通过countDown方法减少计数器数量,await方法等待计数器归零。
CyclicBarrier是一个循环屏障,常用于多个线程协同完成任务。例如:
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> { System.out.println("召唤神龙成功!");});for (int i = 1; i <= 7; i++) { new Thread(() -> { System.out.println(Thread.currentThread().getName() + "搜集" + i + "个龙珠"); try { cyclicBarrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } }).start();} CyclicBarrier的await方法会等待所有参与线程完成任务后才继续。
Semaphore是一个信号量,用于控制资源的使用和线程的互斥。常见用法包括:
Semaphore semaphore = new Semaphore(3);for (int i = 1; i <= 6; i++) { new Thread(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "抢到车位"); TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName() + "离开车位"); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } }, String.valueOf(i)).start();} Semaphore的acquire方法获取信号量,release方法释放信号量。
ReadWriteLock提供了读锁和写锁,允许多个线程同时持有读锁,但只能一个线程持有写锁。常见用法包括:
ReadWriteLock readWriteLock = new ReadWriteLock();for (int i = 1; i <= 5; i++) { new Thread(() -> { myCache.put(temp + "", temp); }, String.valueOf(i)).start();}for (int i = 1; i <= 5; i++) { new Thread(() -> { myCache.get(temp + ""); }, String.valueOf(i)).start();} ReadWriteLock的写锁是独占锁,而读锁是共享锁。
BlockingQueue是一种阻塞队列,支持线程安全的生产和消费。常见实现包括ArrayBlockingQueue和SynchronousQueue。ArrayBlockingQueue有固定容量,会阻塞生产和消费操作;SynchronousQueue没有容量限制,生产和消费操作都需要等待。
ArrayBlockingQueueblockingQueue = new ArrayBlockingQueue<>(3);blockingQueue.put("a");blockingQueue.put("b");blockingQueue.put("c");System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());
SynchronousQueue是一个同步队列,put和take操作必须成对出现。例如:
SynchronousQueuesynchronousQueue = new SynchronousQueue<>();new Thread(() -> { try { System.out.println(Thread.currentThread().getName() + " put 1"); synchronousQueue.put("1"); System.out.println(Thread.currentThread().getName() + " put 2"); synchronousQueue.put("2"); System.out.println(Thread.currentThread().getName() + " put 3"); } catch (InterruptedException e) { e.printStackTrace(); }}, "T1").start();new Thread(() -> { try { TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + " > " + synchronousQueue.take()); TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + " > " + synchronousQueue.take()); TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + " > " + synchronousQueue.take()); } catch (InterruptedException e) { e.printStackTrace(); }}, "T2").start();
线程池是资源池化的典范,通过ThreadPoolExecutor实现。线程池的三大方法包括:
线程池的核心参数包括核心线程池大小、最大线程池大小、线程保持时间和工作队列类型。常见用法包括:
ExecutorService threadPool = Executors.newSingleThreadExecutor();for (int i = 0; i < 100; i++) { threadPool.execute(() -> { System.out.println(Thread.currentThread().getName() + " ok"); });}threadPool.shutdown(); 线程池的四种拒绝策略包括:
线程池的核心优势在于优化资源利用率,降低资源消耗,提高响应速度。
转载地址:http://ertd.baihongyu.com/