本文共 7401 字,大约阅读时间需要 24 分钟。
近期结合自己所学的多线程JUC相关知识点,对Java并发编程几个常见问题进行了总结和思考。以下是对几大问题的详细解答。
Java开启线程的方式主要有以下四种:
在Java中,线程安全的常用方法包括:
Volatile无法保证线程安全,因为它不具备原子性。例如,多个线程同时修改同一个volatile变量可能导致数据不一致。
为了防止指令重排,确保单例的初始化线程安全。例如,双重锁加volatile可以防止初始化时的竞态条件和指令重排问题。
Java的锁机制基于对象的Markword记录锁状态。根据资源竞争的剧烈程度,锁会自动升级:
锁升级是根据资源竞争的严重程度进行的:
AQS(AbstractQueuedSynchronizer)是Java线程的同步框架,用于实现许多锁的基础设施。ReentrantLock的可重入性基于AQS实现。
AQS维护了一个信号量state和一个双向链表队列。state用于控制线程排队或放行,具体意义根据使用场景而定。在可重入锁中,state用于表示加锁的次数(0表示无锁状态)。
可以通过JUC的信号量工具类CountDownLatch或CyclicBarrier实现。例如:
可以利用共享变量的可见性实现线程的有序执行。例如:
static volatile int ticket = 1;public static void main(String[] args) { Thread t1 = new Thread(() -> { while (true) { if (ticket == 1) { try { Thread.sleep(100); System.out.println("a"); ticket = 2; } catch (InterruptedException e) { e.printStackTrace(); } } } }); Thread t2 = new Thread(() -> { while (true) { if (ticket == 2) { try { Thread.sleep(100); System.out.println("b"); ticket = 3; } catch (InterruptedException e) { e.printStackTrace(); } } } }); Thread t3 = new Thread(() -> { while (true) { if (ticket == 3) { try { Thread.sleep(100); System.out.println("c"); ticket = 1; } catch (InterruptedException e) { e.printStackTrace(); } } } }); t1.start(); t2.start(); t3.start();} 可以使用Semaphore信号量或JUC的Condition实现。例如:
private static Semaphore s1 = new Semaphore(1);private static Semaphore s2 = new Semaphore(1);private static Semaphore s3 = new Semaphore(1);public static void main(String[] args) { try { s1.acquire(); s2.acquire(); } catch (InterruptedException e1) { e1.printStackTrace(); } new Thread(() -> { while (true) { try { s1.acquire(); System.out.println("A"); s2.release(); } catch (InterruptedException e) { e.printStackTrace(); } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); new Thread(() -> { while (true) { try { s2.acquire(); System.out.println("B"); s3.release(); } catch (InterruptedException e) { e.printStackTrace(); } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); new Thread(() -> { while (true) { try { s3.acquire(); System.out.println("C"); s1.release(); } catch (InterruptedException e) { e.printStackTrace(); } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }).start();} Fork/Join框架适合对大字符串进行排序。具体实现步骤如下:
ForkJoinPool pool = new ForkJoinPool();MyTask,重写compute方法实现排序。ForkJoinTask(task).submit();task.get();例如:
public class MergeTest { private static int MAX = 100; private static int inits[] = new int[MAX]; static { Random r = new Random(); for (int index = 1; index <= MAX; index++) { inits[index - 1] = r.nextInt(1000); } } public static void main(String[] args) throws Exception { long beginTime = System.currentTimeMillis(); ForkJoinPool pool = new ForkJoinPool(); MyTask task = new MyTask(inits); ForkJoinTask taskResult = pool.submit(task); try { int[] ints = taskResult.get(); System.out.println(Arrays.toString(ints)); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(System.out); } long endTime = System.currentTimeMillis(); System.out.println("耗时=" + (endTime - beginTime)); } static class MyTask extends RecursiveTask { private int source[]; public MyTask(int source[]) { this.source = source; } @Override protected int[] compute() { int sourceLen = source.length; if (sourceLen > 2) { int midIndex = sourceLen / 2; MyTask task1 = new MyTask(Arrays.copyOf(source, midIndex)); task1.fork(); MyTask task2 = new MyTask(Arrays.copyOfRange(source, midIndex, sourceLen)); task2.fork(); return joinInts(task1.join(), task2.join()); } else { if (sourceLen == 1 || source[0] <= source[1]) { return source; } else { int targetp[] = new int[sourceLen]; targetp[0] = source[1]; targetp[1] = source[0]; return targetp; } } } private static int[] joinInts(int array1[], int array2[]) { int destInts[] = new int[array1.length + array2.length]; int array1Len = array1.length; int array2Len = array2.length; for (int index = 0, array1Index = 0, array2Index = 0; index < destInts.length; index++) { int value1 = array1Index >= array1Len ? Integer.MAX_VALUE : array1[array1Index]; int value2 = array2Index >= array2Len ? Integer.MAX_VALUE : array2[array2Index]; if (value1 < value2) { array1Index++; destInts[index] = value1; } else { array2Index++; destInts[index] = value2; } } return destInts; } }} 以上就是对Java并发编程常见问题的总结和思考,希望对理解Java并发编程有所帮助。
转载地址:http://yxsu.baihongyu.com/