• 线程交替输出(你能想出几种方法)


     前提

    关于线程的解决思路,最好不要从时间角度,优先级角度考虑。一般不要使用sleep和join。

    LockSupport

    LockSupport.unpark();
    LockSupport.park();
    
    1. public class A {
    2. static Thread t1 = null;
    3. static Thread t2 = null;
    4. public static void main(String[] args) {
    5. String[] a = {"1","2","3","4","5"};
    6. String[] b = {"a","b","c","d","e"};
    7. t1 = new Thread(new Runnable() {
    8. @Override
    9. public void run() {
    10. for (int i = 0; i < a.length; i++) {
    11. System.out.println(a[i]);
    12. LockSupport.unpark(t2);
    13. LockSupport.park();
    14. }
    15. }
    16. });
    17. t2 = new Thread(()->{
    18. for (int i = 0; i < b.length; i++) {
    19. LockSupport.park();
    20. System.out.println(b[i]);
    21. LockSupport.unpark(t1);
    22. }
    23. });
    24. t1.start();
    25. t2.start();
    26. }
    27. }

    ReentrantLock

    针对线程通信这块,比起使用wait和notify更灵活,因为可以指定多个condition

    lock.newCondition()
    condition.signal();
    condition.await();

     

    1. public class C {
    2. static CountDownLatch latch = new CountDownLatch(1); //可以指定谁先执行时使用,具体看B类
    3. static ReentrantLock lock = new ReentrantLock();
    4. static Condition condition1 = lock.newCondition();
    5. static Condition condition2 = lock.newCondition();
    6. public static void main(String[] args) {
    7. String[] a = {"1","2","3","4","5"};
    8. String[] b = {"a","b","c","d","e"};
    9. C c = new C();
    10. new Thread(()->{
    11. c.t1(a);
    12. }).start();
    13. new Thread(()->{
    14. c.t2(b);
    15. }).start();
    16. }
    17. void t1(String[] a) {
    18. lock.lock();
    19. for (int i = 0; i < a.length; i++) {
    20. try {
    21. System.out.println(a[i]);
    22. condition1.signal();
    23. condition2.await();
    24. } catch (Exception e) {
    25. e.printStackTrace();
    26. }
    27. condition1.signal();
    28. }
    29. lock.unlock();
    30. }
    31. void t2(String[] b){
    32. lock.lock();
    33. for (int i = 0; i < b.length; i++) {
    34. try {
    35. System.out.println(b[i]);
    36. condition2.signal();
    37. condition1.await();
    38. } catch (InterruptedException e) {
    39. e.printStackTrace();
    40. }
    41. condition2.signal();
    42. }
    43. lock.unlock();
    44. }
    45. }

     在这里可以看知道两个线程确实交替执行了(暂时没有控制线程先后顺序),但是,如果我想控制让哪个线程先执行,需要怎么做?想一想,在使用wait和notify的案例中给出答案。

    wait、notify

    synchronized
    notify();
    wait();

     可以看一下如何控制哪个线程先输出

    1. public class B {
    2. static CountDownLatch latch = new CountDownLatch(1);
    3. public static void main(String[] args) {
    4. String[] a = {"1","2","3","4","5"};
    5. String[] b = {"a","b","c","d","e"};
    6. B b1 = new B();
    7. new Thread(()->{
    8. b1.t1(a);
    9. }).start();
    10. new Thread(()->{
    11. b1.t2(b);
    12. }).start();
    13. }
    14. void t1(String[] a) {
    15. try {
    16. latch.await();
    17. } catch (InterruptedException e) {
    18. e.printStackTrace();
    19. }
    20. synchronized (this){
    21. for (int i = 0; i < a.length; i++) {
    22. try {
    23. System.out.println(a[i]);
    24. notify();
    25. wait();
    26. } catch (InterruptedException e) {
    27. e.printStackTrace();
    28. }
    29. }
    30. notify();
    31. }
    32. }
    33. void t2(String[] b){
    34. synchronized (this){
    35. for (int i = 0; i < b.length; i++) {
    36. try {
    37. System.out.println(b[i]);
    38. latch.countDown();
    39. notify();
    40. wait();
    41. } catch (InterruptedException e) {
    42. e.printStackTrace();
    43. }
    44. }
    45. notify();
    46. }
    47. }
    48. }

    LinkedTransferQueue

    LinkedTransferQueue是一个由链表结构组成的无界阻塞TransferQueue队列。

    LinkedTransferQueueSynchronousQueueLinkedBlockingQueue 的合体,性能比 LinkedBlockingQueue 更高(没有锁操作),比 SynchronousQueue能存储更多的元素。

    相对于其他阻塞队列,LinkedTransferQueue多了tryTransfer和transfer方法。

    transfer:调用此方法后要等到有消费者获取此元素之后才返回,不然就一直阻塞。

    take和poll: 如果为空就一直阻塞.

     

    1. public class D {
    2. public static void main(String[] args) {
    3. String[] a = {"1","2","3","4","5"};
    4. String[] b = {"a","b","c","d","e"};
    5. LinkedTransferQueue queue = new LinkedTransferQueue<>();
    6. new Thread(()->{
    7. try {
    8. for (int i = 0; i < a.length; i++) {
    9. System.out.println(queue.take());
    10. queue.transfer(a[i]);
    11. }
    12. } catch (InterruptedException e) {
    13. e.printStackTrace();
    14. }
    15. }).start();
    16. new Thread(()->{
    17. for (int i = 0; i < b.length; i++) {
    18. try {
    19. queue.transfer(b[i]);
    20. System.out.println(queue.take());
    21. } catch (InterruptedException e) {
    22. e.printStackTrace();
    23. }
    24. }
    25. }).start();
    26. }
    27. }

  • 相关阅读:
    如何判断自己适不适合做一名程序员
    .NET Core Hangfire任务计划
    王道链表综合题(下)
    【磐河旅行】之酒店API接口对接实录
    Spring Boot JPA 本机查询示例
    调用线程的run()和start()方法有什么不同呢?
    huggingface下载文件,可以看下载进度
    AC发声:我踩过的坑 你们都(别再)踩了
    JVM入个门(1)
    LRU算法 vs Redis近似LRU算法
  • 原文地址:https://blog.csdn.net/wai_58934/article/details/126256384