├── .idea ├── compiler.xml ├── encodings.xml ├── misc.xml ├── vcs.xml └── workspace.xml ├── Disruptor.md ├── JMH.md ├── JUC.iml ├── README.md ├── pom.xml ├── src └── main │ ├── java │ ├── com │ │ └── mashibing │ │ │ ├── JustTest.java │ │ │ ├── Tets.java │ │ │ ├── disruptor │ │ │ ├── v1 │ │ │ │ ├── LongEvent.java │ │ │ │ ├── LongEventFactory.java │ │ │ │ ├── LongEventHandler.java │ │ │ │ ├── LongEventProducer.java │ │ │ │ └── Main.java │ │ │ ├── v2 │ │ │ │ ├── LongEvent.java │ │ │ │ ├── LongEventFactory.java │ │ │ │ ├── LongEventHandler.java │ │ │ │ ├── LongEventProducer.java │ │ │ │ ├── Main.java │ │ │ │ └── readme │ │ │ ├── v3 │ │ │ │ ├── LongEvent.java │ │ │ │ ├── Main.java │ │ │ │ └── readme │ │ │ └── v4 │ │ │ │ ├── LongEvent.java │ │ │ │ ├── Main.java │ │ │ │ └── readme │ │ │ └── juc │ │ │ ├── c_000 │ │ │ ├── T01_WhatIsThread.java │ │ │ ├── T02_HowToCreateThread.java │ │ │ ├── T03_Sleep_Yield_Join.java │ │ │ └── T04_ThreadState.java │ │ │ ├── c_001 │ │ │ └── T.java │ │ │ ├── c_002 │ │ │ └── T.java │ │ │ ├── c_003 │ │ │ ├── T.java │ │ │ └── T1.java │ │ │ ├── c_004 │ │ │ └── T.java │ │ │ ├── c_005 │ │ │ └── T.java │ │ │ ├── c_006 │ │ │ └── T.java │ │ │ ├── c_007 │ │ │ └── T.java │ │ │ ├── c_008 │ │ │ └── Account.java │ │ │ ├── c_009 │ │ │ └── T.java │ │ │ ├── c_010 │ │ │ └── T.java │ │ │ ├── c_011 │ │ │ └── T.java │ │ │ ├── c_011_01 │ │ │ └── readme │ │ │ ├── c_012_Volatile │ │ │ ├── T01_HelloVolatile.java │ │ │ ├── T02_VolatileReference1.java │ │ │ ├── T03________VolatileReference2.java │ │ │ ├── T04_VolatileNotSync.java │ │ │ └── T05_VolatileVsSync.java │ │ │ ├── c_016_LockOptimization │ │ │ └── FineCoarseLock.java │ │ │ ├── c_017_MoreAboutSync │ │ │ ├── DoNotLockString.java │ │ │ └── SyncSameObject.java │ │ │ ├── c_018_00_AtomicXXX │ │ │ ├── T01_AtomicInteger.java │ │ │ ├── T02_AtomicVsSyncVsLongAdder.java │ │ │ └── T03________SyncVsLongAdder.java │ │ │ ├── c_018_01_Unsafe │ │ │ └── HelloUnsafe.java │ │ │ ├── c_020 │ │ │ ├── T01_ReentrantLock1.java │ │ │ ├── T02_ReentrantLock2.java │ │ │ ├── T03_ReentrantLock3.java │ │ │ ├── T04_ReentrantLock4.java │ │ │ ├── T05_ReentrantLock5.java │ │ │ ├── T06_TestCountDownLatch.java │ │ │ ├── T07_TestCyclicBarrier.java │ │ │ ├── T08_TestPhaser.java │ │ │ ├── T09_TestPhaser2.java │ │ │ ├── T10_TestReadWriteLock.java │ │ │ ├── T11_TestSemaphore.java │ │ │ ├── T12_TestExchanger.java │ │ │ └── T13_TestLockSupport.java │ │ │ ├── c_020_01_Interview │ │ │ ├── T01_WithoutVolatile.java │ │ │ ├── T02_WithVolatile.java │ │ │ ├── T03_NotifyHoldingLock.java │ │ │ ├── T04_NotifyFreeLock.java │ │ │ ├── T05_CountDownLatch.java │ │ │ ├── T06_LockSupport.java │ │ │ ├── T07_LockSupport_WithoutSleep.java │ │ │ └── T08_Semaphore.java │ │ │ ├── c_021_01_interview │ │ │ ├── MyContainer1.java │ │ │ └── MyContainer2.java │ │ │ ├── c_021_02_AQS │ │ │ ├── MLock.java │ │ │ ├── Main.java │ │ │ ├── Sync.java │ │ │ └── TestReentrantLock.java │ │ │ ├── c_021_03_VarHandle │ │ │ └── T01_HelloVarHandle.java │ │ │ ├── c_022_RefTypeAndThreadLocal │ │ │ ├── M.java │ │ │ ├── T01_NormalReference.java │ │ │ ├── T02_SoftReference.java │ │ │ ├── T03_WeakReference.java │ │ │ ├── T04_PhantomReference.java │ │ │ ├── ThreadLocal1.java │ │ │ └── ThreadLocal2.java │ │ │ ├── c_023 │ │ │ └── Singleton.java │ │ │ ├── c_023_01_Containers │ │ │ ├── HelloQueue.java │ │ │ ├── T01_HelloArray.java │ │ │ └── T02_CollectionListSetQueue.java │ │ │ ├── c_023_02_FromHashtableToCHM │ │ │ ├── Constants.java │ │ │ ├── T01_TestHashtable.java │ │ │ ├── T02_TestHashMap.java │ │ │ ├── T03_TestSynchronizedHashMap.java │ │ │ └── T04_TestConcurrentHashMap.java │ │ │ ├── c_024_FromVectorToQueue │ │ │ ├── TicketSeller1.java │ │ │ ├── TicketSeller2.java │ │ │ ├── TicketSeller3.java │ │ │ ├── TicketSeller4.java │ │ │ └── readme.txt │ │ │ ├── c_025 │ │ │ ├── T01_ConcurrentMap.java │ │ │ ├── T02_CopyOnWriteList.java │ │ │ ├── T03_SynchronizedList.java │ │ │ ├── T04_ConcurrentQueue.java │ │ │ ├── T05_LinkedBlockingQueue.java │ │ │ ├── T06_ArrayBlockingQueue.java │ │ │ ├── T07_01_PriorityQueque.java │ │ │ ├── T07_DelayQueue.java │ │ │ ├── T08_SynchronusQueue.java │ │ │ ├── T09_TransferQueue.java │ │ │ └── readme.txt │ │ │ ├── c_026_00_interview │ │ │ └── A1B2C3 │ │ │ │ ├── T01_00_Question.java │ │ │ │ ├── T02_00_LockSupport.java │ │ │ │ ├── T03_00_cas.java │ │ │ │ ├── T04_00_BlockingQueue.java │ │ │ │ ├── T05_00_AtomicInteger.java │ │ │ │ ├── T06_00_sync_wait_notify.java │ │ │ │ ├── T07_00_sync_wait_notify.java │ │ │ │ ├── T08_00_lock_condition.java │ │ │ │ ├── T09_00_lock_condition.java │ │ │ │ ├── T10_00_PipedStream.java │ │ │ │ ├── T12_00_Exchanger_Not_Work.java │ │ │ │ ├── T13_TransferQueue.java │ │ │ │ └── readme │ │ │ ├── c_026_01_ThreadPool │ │ │ ├── T01_MyExecutor.java │ │ │ ├── T02_ExecutorService.java │ │ │ ├── T03_Callable.java │ │ │ ├── T04_Executors.java │ │ │ ├── T05_00_HelloThreadPool.java │ │ │ ├── T05_ThreadPool.java │ │ │ ├── T06_00_Future.java │ │ │ ├── T06_01_CompletableFuture.java │ │ │ ├── T07_SingleThreadPool.java │ │ │ ├── T08_CachedPool.java │ │ │ ├── T09_FixedThreadPool.java │ │ │ ├── T10_ScheduledPool.java │ │ │ ├── T11_WorkStealingPool.java │ │ │ ├── T12_ForkJoinPool.java │ │ │ ├── T13_ParallelStreamAPI.java │ │ │ ├── T14_MyRejectedHandler.java │ │ │ ├── ThreadPoolExecutor源码解析.md │ │ │ └── readme.txt │ │ │ ├── c_027_future_to_loom │ │ │ ├── T01_Future.java │ │ │ └── T02_ListenableFuture.java │ │ │ ├── c_028_FalseSharing │ │ │ ├── T01_CacheLinePadding.java │ │ │ └── T02_CacheLinePadding.java │ │ │ └── c_029_WriteCombining │ │ │ └── WriteCombining.java │ └── 思考题.txt │ └── resources │ └── Test.puml └── target └── classes ├── META-INF └── JUC.kotlin_module └── Test.puml /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 90 | 91 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 119 | 120 | 121 | 122 | synchronized 123 | compare 124 | incrementand 125 | compareandset 126 | all 127 | sun.mi 128 | onadv 129 | set 130 | synchronizedMap 131 | synchronizedList 132 | Fork 133 | 134 | 135 | 136 | 138 | 139 | 194 | 195 | 196 | 201 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 291 | 292 | 293 | 294 | 306 | 307 | 319 | 320 | 332 | 333 | 345 | 346 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 1565232818446 385 | 389 | 390 | 1566616292953 391 | 396 | 397 | 1567908240513 398 | 403 | 404 | 1569205605236 405 | 410 | 411 | 1569727444423 412 | 417 | 418 | 1570803022734 419 | 424 | 425 | 1571235524344 426 | 431 | 432 | 1573357300351 433 | 438 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 508 | 509 | 510 | 511 | 512 | file://$PROJECT_DIR$/src/main/java/com/mashibing/juc/c_020/T11_TestSemaphore.java 513 | 12 514 | 515 | 517 | 518 | jar://C:/Program Files/Java/jdk-11.0.3/lib/src.zip!/java.base/java/util/concurrent/locks/ReentrantLock.java 519 | 126 520 | 521 | 523 | 524 | file://$PROJECT_DIR$/src/main/java/com/mashibing/juc/c_021_02_AQS/TestReentrantLock.java 525 | 10 526 | 527 | 529 | 530 | jar://C:/Program Files/Java/jdk1.7.0_80/src.zip!/java/util/concurrent/ConcurrentHashMap.java 531 | 807 532 | 533 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 938 | 939 | 940 | 941 | 942 | 943 | No facets are configured 944 | 945 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 961 | 962 | 963 | 964 | 965 | 966 | 11 967 | 968 | 973 | 974 | 975 | 976 | 977 | 978 | JUC 979 | 980 | 985 | 986 | 987 | 988 | 989 | 990 | Maven: com.lmax:disruptor:3.4.2 991 | 992 | 997 | 998 | 999 | 1000 | 1001 | 1002 | -------------------------------------------------------------------------------- /Disruptor.md: -------------------------------------------------------------------------------- 1 | # Disruptor 2 | 3 | 作者:马士兵 http://www.mashibing.com 4 | 5 | 最近更新:2019年10月22日 6 | 7 | ## 介绍 8 | 9 | 主页:http://lmax-exchange.github.io/disruptor/ 10 | 11 | 源码:https://github.com/LMAX-Exchange/disruptor 12 | 13 | GettingStarted: https://github.com/LMAX-Exchange/disruptor/wiki/Getting-Started 14 | 15 | api: http://lmax-exchange.github.io/disruptor/docs/index.html 16 | 17 | maven: https://mvnrepository.com/artifact/com.lmax/disruptor 18 | 19 | ## Disruptor的特点 20 | 21 | 对比ConcurrentLinkedQueue : 链表实现 22 | 23 | JDK中没有ConcurrentArrayQueue 24 | 25 | Disruptor是数组实现的 26 | 27 | 无锁,高并发,使用环形Buffer,直接覆盖(不用清除)旧的数据,降低GC频率 28 | 29 | 实现了基于事件的生产者消费者模式(观察者模式) 30 | 31 | ## RingBuffer 32 | 33 | 环形队列 34 | 35 | RingBuffer的序号,指向下一个可用的元素 36 | 37 | 采用数组实现,没有首尾指针 38 | 39 | 对比ConcurrentLinkedQueue,用数组实现的速度更快 40 | 41 | > 假如长度为8,当添加到第12个元素的时候在哪个序号上呢?用12%8决定 42 | > 43 | > 当Buffer被填满的时候到底是覆盖还是等待,由Producer决定 44 | > 45 | > 长度设为2的n次幂,利于二进制计算,例如:12%8 = 12 & (8 - 1) pos = num & (size -1) 46 | 47 | ## Disruptor开发步骤 48 | 49 | 1. 定义Event - 队列中需要处理的元素 50 | 51 | 2. 定义Event工厂,用于填充队列 52 | 53 | > 这里牵扯到效率问题:disruptor初始化的时候,会调用Event工厂,对ringBuffer进行内存的提前分配 54 | > 55 | > GC产频率会降低 56 | 57 | 3. 定义EventHandler(消费者),处理容器中的元素 58 | 59 | ## 事件发布模板 60 | 61 | ```java 62 | long sequence = ringBuffer.next(); // Grab the next sequence 63 | try { 64 | LongEvent event = ringBuffer.get(sequence); // Get the entry in the Disruptor 65 | // for the sequence 66 | event.set(8888L); // Fill with data 67 | } finally { 68 | ringBuffer.publish(sequence); 69 | } 70 | ``` 71 | 72 | ## 使用EventTranslator发布事件 73 | 74 | ```java 75 | //=============================================================== 76 | EventTranslator translator1 = new EventTranslator() { 77 | @Override 78 | public void translateTo(LongEvent event, long sequence) { 79 | event.set(8888L); 80 | } 81 | }; 82 | 83 | ringBuffer.publishEvent(translator1); 84 | 85 | //=============================================================== 86 | EventTranslatorOneArg translator2 = new EventTranslatorOneArg() { 87 | @Override 88 | public void translateTo(LongEvent event, long sequence, Long l) { 89 | event.set(l); 90 | } 91 | }; 92 | 93 | ringBuffer.publishEvent(translator2, 7777L); 94 | 95 | //=============================================================== 96 | EventTranslatorTwoArg translator3 = new EventTranslatorTwoArg() { 97 | @Override 98 | public void translateTo(LongEvent event, long sequence, Long l1, Long l2) { 99 | event.set(l1 + l2); 100 | } 101 | }; 102 | 103 | ringBuffer.publishEvent(translator3, 10000L, 10000L); 104 | 105 | //=============================================================== 106 | EventTranslatorThreeArg translator4 = new EventTranslatorThreeArg() { 107 | @Override 108 | public void translateTo(LongEvent event, long sequence, Long l1, Long l2, Long l3) { 109 | event.set(l1 + l2 + l3); 110 | } 111 | }; 112 | 113 | ringBuffer.publishEvent(translator4, 10000L, 10000L, 1000L); 114 | 115 | //=============================================================== 116 | EventTranslatorVararg translator5 = new EventTranslatorVararg() { 117 | 118 | @Override 119 | public void translateTo(LongEvent event, long sequence, Object... objects) { 120 | long result = 0; 121 | for(Object o : objects) { 122 | long l = (Long)o; 123 | result += l; 124 | } 125 | event.set(result); 126 | } 127 | }; 128 | 129 | ringBuffer.publishEvent(translator5, 10000L, 10000L, 10000L, 10000L); 130 | ``` 131 | 132 | ## 使用Lamda表达式 133 | 134 | ```java 135 | package com.mashibing.disruptor; 136 | 137 | import com.lmax.disruptor.RingBuffer; 138 | import com.lmax.disruptor.dsl.Disruptor; 139 | import com.lmax.disruptor.util.DaemonThreadFactory; 140 | 141 | public class Main03 142 | { 143 | public static void main(String[] args) throws Exception 144 | { 145 | // Specify the size of the ring buffer, must be power of 2. 146 | int bufferSize = 1024; 147 | 148 | // Construct the Disruptor 149 | Disruptor disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE); 150 | 151 | // Connect the handler 152 | disruptor.handleEventsWith((event, sequence, endOfBatch) -> System.out.println("Event: " + event)); 153 | 154 | // Start the Disruptor, starts all threads running 155 | disruptor.start(); 156 | 157 | // Get the ring buffer from the Disruptor to be used for publishing. 158 | RingBuffer ringBuffer = disruptor.getRingBuffer(); 159 | 160 | 161 | ringBuffer.publishEvent((event, sequence) -> event.set(10000L)); 162 | 163 | System.in.read(); 164 | } 165 | } 166 | ``` 167 | 168 | ## ProducerType生产者线程模式 169 | 170 | > ProducerType有两种模式 Producer.MULTI和Producer.SINGLE 171 | > 172 | > 默认是MULTI,表示在多线程模式下产生sequence 173 | > 174 | > 如果确认是单线程生产者,那么可以指定SINGLE,效率会提升 175 | > 176 | > 如果是多个生产者(多线程),但模式指定为SINGLE,会出什么问题呢? 177 | 178 | ## 等待策略 179 | 180 | 1,(常用)BlockingWaitStrategy:通过线程阻塞的方式,等待生产者唤醒,被唤醒后,再循环检查依赖的sequence是否已经消费。 181 | 182 | 2,BusySpinWaitStrategy:线程一直自旋等待,可能比较耗cpu 183 | 184 | 3,LiteBlockingWaitStrategy:线程阻塞等待生产者唤醒,与BlockingWaitStrategy相比,区别在signalNeeded.getAndSet,如果两个线程同时访问一个访问waitfor,一个访问signalAll时,可以减少lock加锁次数. 185 | 186 | 4,LiteTimeoutBlockingWaitStrategy:与LiteBlockingWaitStrategy相比,设置了阻塞时间,超过时间后抛异常。 187 | 188 | 5,PhasedBackoffWaitStrategy:根据时间参数和传入的等待策略来决定使用哪种等待策略 189 | 190 | 6,TimeoutBlockingWaitStrategy:相对于BlockingWaitStrategy来说,设置了等待时间,超过后抛异常 191 | 192 | 7,(常用)YieldingWaitStrategy:尝试100次,然后Thread.yield()让出cpu 193 | 194 | 8. (常用)SleepingWaitStrategy : sleep 195 | 196 | ## 消费者异常处理 197 | 198 | 默认:disruptor.setDefaultExceptionHandler() 199 | 200 | 覆盖:disruptor.handleExceptionFor().with() 201 | 202 | ## 依赖处理 203 | 204 | -------------------------------------------------------------------------------- /JMH.md: -------------------------------------------------------------------------------- 1 | # JMH Java准测试工具套件 2 | 3 | ## 什么是JMH 4 | 5 | ### 官网 6 | 7 | http://openjdk.java.net/projects/code-tools/jmh/ 8 | 9 | ## 创建JMH测试 10 | 11 | 1. 创建Maven项目,添加依赖 12 | 13 | ```java 14 | 15 | 18 | 4.0.0 19 | 20 | 21 | UTF-8 22 | UTF-8 23 | 1.8 24 | 1.8 25 | 1.8 26 | 27 | 28 | mashibing.com 29 | HelloJMH2 30 | 1.0-SNAPSHOT 31 | 32 | 33 | 34 | 35 | 36 | org.openjdk.jmh 37 | jmh-core 38 | 1.21 39 | 40 | 41 | 42 | 43 | org.openjdk.jmh 44 | jmh-generator-annprocess 45 | 1.21 46 | test 47 | 48 | 49 | 50 | 51 | 52 | ``` 53 | 54 | 2. idea安装JMH插件 JMH plugin v1.0.3 55 | 56 | 3. 由于用到了注解,打开运行程序注解配置 57 | 58 | > compiler -> Annotation Processors -> Enable Annotation Processing 59 | 60 | 4. 定义需要测试类PS (ParallelStream) 61 | 62 | ```java 63 | package com.mashibing.jmh; 64 | 65 | import java.util.ArrayList; 66 | import java.util.List; 67 | import java.util.Random; 68 | 69 | public class PS { 70 | 71 | static List nums = new ArrayList<>(); 72 | static { 73 | Random r = new Random(); 74 | for (int i = 0; i < 10000; i++) nums.add(1000000 + r.nextInt(1000000)); 75 | } 76 | 77 | static void foreach() { 78 | nums.forEach(v->isPrime(v)); 79 | } 80 | 81 | static void parallel() { 82 | nums.parallelStream().forEach(PS::isPrime); 83 | } 84 | 85 | static boolean isPrime(int num) { 86 | for(int i=2; i<=num/2; i++) { 87 | if(num % i == 0) return false; 88 | } 89 | return true; 90 | } 91 | } 92 | ``` 93 | 94 | 5. 写单元测试 95 | 96 | > 这个测试类一定要在test package下面 97 | > 98 | > ```java 99 | > package com.mashibing.jmh; 100 | > 101 | > import org.openjdk.jmh.annotations.Benchmark; 102 | > 103 | > import static org.junit.jupiter.api.Assertions.*; 104 | > 105 | > public class PSTest { 106 | > @Benchmark 107 | > public void testForEach() { 108 | > PS.foreach(); 109 | > } 110 | > } 111 | > ``` 112 | 113 | 6. 运行测试类,如果遇到下面的错误: 114 | 115 | ```java 116 | ERROR: org.openjdk.jmh.runner.RunnerException: ERROR: Exception while trying to acquire the JMH lock (C:\WINDOWS\/jmh.lock): C:\WINDOWS\jmh.lock (拒绝访问。), exiting. Use -Djmh.ignoreLock=true to forcefully continue. 117 | at org.openjdk.jmh.runner.Runner.run(Runner.java:216) 118 | at org.openjdk.jmh.Main.main(Main.java:71) 119 | ``` 120 | 121 | 这个错误是因为JMH运行需要访问系统的TMP目录,解决办法是: 122 | 123 | 打开RunConfiguration -> Environment Variables -> include system environment viables 124 | 125 | 7. 阅读测试报告 126 | 127 | ## JMH中的基本概念 128 | 129 | 1. Warmup 130 | 预热,由于JVM中对于特定代码会存在优化(本地化),预热对于测试结果很重要 131 | 2. Mesurement 132 | 总共执行多少次测试 133 | 3. Timeout 134 | 135 | 4. Threads 136 | 线程数,由fork指定 137 | 5. Benchmark mode 138 | 基准测试的模式 139 | 6. Benchmark 140 | 测试哪一段代码 141 | 142 | ## Next 143 | 144 | 官方样例: 145 | http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/ 146 | 147 | -------------------------------------------------------------------------------- /JUC.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JUC 2 | 多线程与高并发 3 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | mashibing.com 8 | JUC 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 1.8 13 | 1.8 14 | 15 | 16 | 17 | 18 | 19 | com.google.guava 20 | guava 21 | 28.0-jre 22 | 23 | 24 | 25 | com.lmax 26 | disruptor 27 | 3.4.2 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/JustTest.java: -------------------------------------------------------------------------------- 1 | package com.mashibing; 2 | 3 | public class JustTest { 4 | public static void main(String[] args) { 5 | Object o = new Object(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/Tets.java: -------------------------------------------------------------------------------- 1 | package com.mashibing; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | public class Tets { 6 | public static void main(String[] args) { 7 | ConcurrentHashMap map = new ConcurrentHashMap(); 8 | map.put("1", "msb"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v1/LongEvent.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v1; 2 | 3 | public class LongEvent { 4 | private long value; 5 | 6 | public long getValue() { 7 | return value; 8 | } 9 | 10 | public void setValue(long value) { 11 | this.value = value; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v1/LongEventFactory.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v1; 2 | 3 | import com.lmax.disruptor.EventFactory; 4 | 5 | public class LongEventFactory implements EventFactory { 6 | 7 | public LongEvent newInstance() { 8 | return new LongEvent(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v1/LongEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v1; 2 | 3 | import com.lmax.disruptor.EventHandler; 4 | 5 | public class LongEventHandler implements EventHandler { 6 | public void onEvent(LongEvent longEvent, long l, boolean b) throws Exception { 7 | System.out.println(longEvent.getValue()); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v1/LongEventProducer.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v1; 2 | 3 | import com.lmax.disruptor.RingBuffer; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | public class LongEventProducer { 8 | private final RingBuffer ringBuffer; 9 | 10 | public LongEventProducer(RingBuffer ringBuffer) { 11 | this.ringBuffer = ringBuffer; 12 | } 13 | 14 | public void onData(ByteBuffer buffer) { 15 | long sequence = ringBuffer.next(); 16 | try { 17 | LongEvent event = ringBuffer.get(sequence); 18 | event.setValue(buffer.getLong(0)); 19 | } finally { 20 | ringBuffer.publish(sequence); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v1/Main.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v1; 2 | 3 | import com.lmax.disruptor.RingBuffer; 4 | import com.lmax.disruptor.dsl.Disruptor; 5 | 6 | import java.nio.ByteBuffer; 7 | import java.util.concurrent.Executor; 8 | import java.util.concurrent.Executors; 9 | 10 | public class Main { 11 | public static void main(String[] args) { 12 | //Executor executor = Executors.newCachedThreadPool(); 13 | 14 | LongEventFactory factory = new LongEventFactory(); 15 | 16 | //must be power of 2 17 | int ringBufferSize = 1024; 18 | 19 | Disruptor disruptor = new Disruptor(factory, ringBufferSize, Executors.defaultThreadFactory()); 20 | 21 | disruptor.handleEventsWith(new LongEventHandler()); 22 | 23 | disruptor.start(); 24 | 25 | RingBuffer ringBuffer = disruptor.getRingBuffer(); 26 | 27 | LongEventProducer producer = new LongEventProducer(ringBuffer); 28 | 29 | ByteBuffer bb = ByteBuffer.allocate(8); 30 | 31 | for(long l = 0; l<100; l++) { 32 | bb.putLong(0, l); 33 | 34 | producer.onData(bb); 35 | 36 | try { 37 | Thread.sleep(100); 38 | } catch (InterruptedException e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | 43 | disruptor.shutdown(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v2/LongEvent.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v2; 2 | 3 | public class LongEvent { 4 | private long value; 5 | 6 | public long getValue() { 7 | return value; 8 | } 9 | 10 | public void setValue(long value) { 11 | this.value = value; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v2/LongEventFactory.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v2; 2 | 3 | import com.lmax.disruptor.EventFactory; 4 | 5 | public class LongEventFactory implements EventFactory { 6 | 7 | public LongEvent newInstance() { 8 | return new LongEvent(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v2/LongEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v2; 2 | 3 | import com.lmax.disruptor.EventHandler; 4 | 5 | public class LongEventHandler implements EventHandler { 6 | public void onEvent(LongEvent longEvent, long l, boolean b) throws Exception { 7 | System.out.println(longEvent.getValue()); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v2/LongEventProducer.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v2; 2 | 3 | import com.lmax.disruptor.EventTranslator; 4 | import com.lmax.disruptor.EventTranslatorOneArg; 5 | import com.lmax.disruptor.RingBuffer; 6 | 7 | import java.nio.ByteBuffer; 8 | 9 | public class LongEventProducer { 10 | private final RingBuffer ringBuffer; 11 | 12 | private static final EventTranslatorOneArg TRANSLATOR = new EventTranslatorOneArg() { 13 | @Override 14 | public void translateTo(LongEvent event, long sequence, ByteBuffer bb) { 15 | event.setValue(bb.getLong(0)); 16 | } 17 | }; 18 | 19 | public LongEventProducer(RingBuffer ringBuffer) { 20 | this.ringBuffer = ringBuffer; 21 | } 22 | 23 | public void onData(ByteBuffer buffer) { 24 | ringBuffer.publishEvent(TRANSLATOR, buffer); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v2/Main.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v2; 2 | 3 | import com.lmax.disruptor.RingBuffer; 4 | import com.lmax.disruptor.dsl.Disruptor; 5 | 6 | import java.nio.ByteBuffer; 7 | import java.util.concurrent.Executor; 8 | import java.util.concurrent.ExecutorService; 9 | import java.util.concurrent.Executors; 10 | 11 | public class Main { 12 | public static void main(String[] args) { 13 | //ExecutorService executor = Executors.newCachedThreadPool(); 14 | 15 | LongEventFactory factory = new LongEventFactory(); 16 | 17 | //must be power of 2 18 | int ringBufferSize = 1024; 19 | 20 | Disruptor disruptor = new Disruptor(factory, ringBufferSize, Executors.defaultThreadFactory()); 21 | 22 | disruptor.handleEventsWith(new LongEventHandler()); 23 | 24 | disruptor.start(); 25 | 26 | RingBuffer ringBuffer = disruptor.getRingBuffer(); 27 | 28 | LongEventProducer producer = new LongEventProducer(ringBuffer); 29 | 30 | ByteBuffer bb = ByteBuffer.allocate(8); 31 | 32 | for(long l = 0; true; l++) { 33 | bb.putLong(0, 1); 34 | 35 | producer.onData(bb); 36 | 37 | try { 38 | Thread.sleep(100); 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v2/readme: -------------------------------------------------------------------------------- 1 | 修改LongEventProducer 2 | 将事件的发布过程封装到EventTranslator 3 | 减少了对于ringbuffer的直接操作 4 | 同时可以将Translator单独出来,方便进行单元测试 -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v3/LongEvent.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v3; 2 | 3 | public class LongEvent { 4 | private long value; 5 | 6 | public long getValue() { 7 | return value; 8 | } 9 | 10 | public void setValue(long value) { 11 | this.value = value; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v3/Main.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v3; 2 | 3 | import com.lmax.disruptor.EventHandler; 4 | import com.lmax.disruptor.RingBuffer; 5 | import com.lmax.disruptor.dsl.Disruptor; 6 | import com.lmax.disruptor.util.DaemonThreadFactory; 7 | 8 | import java.nio.ByteBuffer; 9 | import java.util.concurrent.Executors; 10 | 11 | public class Main { 12 | public static void main(String[] args) { 13 | int bufferSize = 1024; 14 | 15 | // Construct the Disruptor 16 | Disruptor disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE); 17 | 18 | // Connect the handler 19 | disruptor.handleEventsWith((event, sequence, endOfBatch) -> System.out.println(event.getValue())); 20 | 21 | // Start the Disruptor, starts all threads running 22 | disruptor.start(); 23 | 24 | // Get the ring buffer from the Disruptor to be used for publishing. 25 | RingBuffer ringBuffer = disruptor.getRingBuffer(); 26 | 27 | ByteBuffer bb = ByteBuffer.allocate(8); 28 | for (long l = 0; true; l++) 29 | { 30 | bb.putLong(0, l); 31 | ringBuffer.publishEvent((event, sequence, buffer) -> event.setValue(buffer.getLong(0)), bb); 32 | 33 | //ringBuffer.publishEvent((event, sequence) -> event.setValue(bb.getLong(0))); 34 | 35 | try { 36 | Thread.sleep(1000); 37 | } catch (InterruptedException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v3/readme: -------------------------------------------------------------------------------- 1 | 修改Main,使用LambdaAPI 2 | 不再使用LongEventFactory 改用LongEvent::new 3 | 4 | 不推荐下面这种写法 5 | ringBuffer.publishEvent((event, sequence) -> event.setValue(bb.getLong(0))); 6 | 7 | 原因是这是一个capturing lambda, 每一个lamda会产生一个对象来承接bb,这样会产生大量的小对象 -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v4/LongEvent.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v4; 2 | 3 | public class LongEvent { 4 | private long value; 5 | 6 | public long getValue() { 7 | return value; 8 | } 9 | 10 | public void setValue(long value) { 11 | this.value = value; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v4/Main.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.disruptor.v4; 2 | 3 | import com.lmax.disruptor.RingBuffer; 4 | import com.lmax.disruptor.dsl.Disruptor; 5 | import com.lmax.disruptor.util.DaemonThreadFactory; 6 | 7 | import java.nio.ByteBuffer; 8 | 9 | public class Main { 10 | 11 | public static void handleEvent(LongEvent event, long sequence, boolean endOfBatch) 12 | { 13 | System.out.println(event); 14 | } 15 | 16 | public static void translate(LongEvent event, long sequence, ByteBuffer buffer) 17 | { 18 | event.setValue(buffer.getLong(0)); 19 | } 20 | 21 | public static void main(String[] args) throws Exception 22 | { 23 | // Specify the size of the ring buffer, must be power of 2. 24 | int bufferSize = 1024; 25 | 26 | // Construct the Disruptor 27 | Disruptor disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE); 28 | 29 | // Connect the handler 30 | disruptor.handleEventsWith(Main::handleEvent); 31 | 32 | // Start the Disruptor, starts all threads running 33 | disruptor.start(); 34 | 35 | // Get the ring buffer from the Disruptor to be used for publishing. 36 | RingBuffer ringBuffer = disruptor.getRingBuffer(); 37 | 38 | ByteBuffer bb = ByteBuffer.allocate(8); 39 | for (long l = 0; true; l++) 40 | { 41 | bb.putLong(0, l); 42 | ringBuffer.publishEvent(Main::translate, bb); 43 | Thread.sleep(1000); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/disruptor/v4/readme: -------------------------------------------------------------------------------- 1 | 最好的写法 -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_000/T01_WhatIsThread.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_000; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | public class T01_WhatIsThread { 6 | private static class T1 extends Thread { 7 | @Override 8 | public void run() { 9 | for(int i=0; i<10; i++) { 10 | try { 11 | TimeUnit.MICROSECONDS.sleep(1); 12 | } catch (InterruptedException e) { 13 | e.printStackTrace(); 14 | } 15 | System.out.println("T1"); 16 | } 17 | } 18 | } 19 | 20 | public static void main(String[] args) { 21 | //new T1().run(); 22 | new T1().start(); 23 | for(int i=0; i<10; i++) { 24 | try { 25 | TimeUnit.MICROSECONDS.sleep(1); 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | System.out.println("main"); 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_000/T02_HowToCreateThread.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_000; 2 | 3 | public class T02_HowToCreateThread { 4 | static class MyThread extends Thread { 5 | @Override 6 | public void run() { 7 | System.out.println("Hello MyThread!"); 8 | } 9 | } 10 | 11 | static class MyRun implements Runnable { 12 | @Override 13 | public void run() { 14 | System.out.println("Hello MyRun!"); 15 | } 16 | } 17 | 18 | public static void main(String[] args) { 19 | new MyThread().start(); 20 | new Thread(new MyRun()).start(); 21 | new Thread(()->{ 22 | System.out.println("Hello Lambda!"); 23 | }).start(); 24 | } 25 | 26 | } 27 | 28 | //请你告诉我启动线程的三种方式 1:Thread 2: Runnable 3:Executors.newCachedThrad 29 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_000/T03_Sleep_Yield_Join.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_000; 2 | 3 | public class T03_Sleep_Yield_Join { 4 | public static void main(String[] args) { 5 | // testSleep(); 6 | // testYield(); 7 | testJoin(); 8 | } 9 | 10 | static void testSleep() { 11 | new Thread(()->{ 12 | for(int i=0; i<100; i++) { 13 | System.out.println("A" + i); 14 | try { 15 | Thread.sleep(500); 16 | //TimeUnit.Milliseconds.sleep(500) 17 | } catch (InterruptedException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | }).start(); 22 | } 23 | 24 | static void testYield() { 25 | new Thread(()->{ 26 | for(int i=0; i<100; i++) { 27 | System.out.println("A" + i); 28 | if(i%10 == 0) Thread.yield(); 29 | 30 | 31 | } 32 | }).start(); 33 | 34 | new Thread(()->{ 35 | for(int i=0; i<100; i++) { 36 | System.out.println("------------B" + i); 37 | if(i%10 == 0) Thread.yield(); 38 | } 39 | }).start(); 40 | } 41 | 42 | static void testJoin() { 43 | Thread t1 = new Thread(()->{ 44 | for(int i=0; i<100; i++) { 45 | System.out.println("A" + i); 46 | try { 47 | Thread.sleep(500); 48 | //TimeUnit.Milliseconds.sleep(500) 49 | } catch (InterruptedException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | }); 54 | 55 | Thread t2 = new Thread(()->{ 56 | 57 | try { 58 | t1.join(); 59 | } catch (InterruptedException e) { 60 | e.printStackTrace(); 61 | } 62 | 63 | for(int i=0; i<100; i++) { 64 | System.out.println("A" + i); 65 | try { 66 | Thread.sleep(500); 67 | //TimeUnit.Milliseconds.sleep(500) 68 | } catch (InterruptedException e) { 69 | e.printStackTrace(); 70 | } 71 | } 72 | }); 73 | 74 | t1.start(); 75 | t2.start(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_000/T04_ThreadState.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_000; 2 | 3 | public class T04_ThreadState { 4 | 5 | static class MyThread extends Thread { 6 | @Override 7 | public void run() { 8 | System.out.println(this.getState()); 9 | 10 | for(int i=0; i<10; i++) { 11 | try { 12 | Thread.sleep(500); 13 | } catch (InterruptedException e) { 14 | e.printStackTrace(); 15 | } 16 | 17 | System.out.println(i); 18 | } 19 | } 20 | } 21 | 22 | public static void main(String[] args) { 23 | Thread t = new MyThread(); 24 | 25 | System.out.println(t.getState()); 26 | 27 | t.start(); 28 | 29 | try { 30 | t.join(); 31 | } catch (InterruptedException e) { 32 | e.printStackTrace(); 33 | } 34 | 35 | System.out.println(t.getState()); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_001/T.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_001/T.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_002/T.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_002/T.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_003/T.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_003/T.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_003/T1.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_003/T1.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_004/T.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_004/T.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_005/T.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_005/T.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_006/T.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_006/T.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_007/T.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_007/T.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_008/Account.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_008/Account.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_009/T.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_009/T.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_010/T.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_010/T.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_011/T.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 程序在执行过程中,如果出现异常,默认情况锁会被释放 3 | * 所以,在并发处理的过程中,有异常要多加小心,不然可能会发生不一致的情况。 4 | * 比如,在一个web app处理过程中,多个servlet线程共同访问同一个资源,这时如果异常处理不合适, 5 | * 在第一个线程中抛出异常,其他线程就会进入同步代码区,有可能会访问到异常产生时的数据。 6 | * 因此要非常小心的处理同步业务逻辑中的异常 7 | * @author mashibing 8 | */ 9 | package com.mashibing.juc.c_011; 10 | 11 | import java.util.concurrent.TimeUnit; 12 | 13 | public class T { 14 | int count = 0; 15 | synchronized void m() { 16 | System.out.println(Thread.currentThread().getName() + " start"); 17 | while(true) { 18 | count ++; 19 | System.out.println(Thread.currentThread().getName() + " count = " + count); 20 | try { 21 | TimeUnit.SECONDS.sleep(1); 22 | 23 | } catch (InterruptedException e) { 24 | e.printStackTrace(); 25 | } 26 | 27 | if(count == 5) { 28 | int i = 1/0; //此处抛出异常,锁将被释放,要想不被释放,可以在这里进行catch,然后让循环继续 29 | System.out.println(i); 30 | } 31 | } 32 | } 33 | 34 | public static void main(String[] args) { 35 | T t = new T(); 36 | Runnable r = new Runnable() { 37 | 38 | @Override 39 | public void run() { 40 | t.m(); 41 | } 42 | 43 | }; 44 | new Thread(r, "t1").start(); 45 | 46 | try { 47 | TimeUnit.SECONDS.sleep(3); 48 | } catch (InterruptedException e) { 49 | e.printStackTrace(); 50 | } 51 | 52 | new Thread(r, "t2").start(); 53 | } 54 | 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_011_01/readme: -------------------------------------------------------------------------------- 1 | synchronized的底层实现 2 | JDK早期的 重量级 - OS 3 | 后来的改进 4 | 锁升级的概念: 5 | 我就是厕所所长 (一 二) 6 | 7 | sync (Object) 8 | markword 记录这个线程ID (偏向锁) 9 | 如果线程争用:升级为 自旋锁 10 | 10次以后, 11 | 升级为重量级锁 - OS 12 | 13 | 执行时间短(加锁代码),线程数少,用自旋 14 | 执行时间长,线程数多,用系统锁 15 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_012_Volatile/T01_HelloVolatile.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_012_Volatile/T01_HelloVolatile.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_012_Volatile/T02_VolatileReference1.java: -------------------------------------------------------------------------------- 1 | /** 2 | * volatile 引用类型(包括数组)只能保证引用本身的可见性,不能保证内部字段的可见性 3 | */ 4 | package com.mashibing.juc.c_012_Volatile; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | public class T02_VolatileReference1 { 9 | 10 | boolean running = true; 11 | 12 | volatile static T02_VolatileReference1 T = new T02_VolatileReference1(); 13 | 14 | 15 | void m() { 16 | System.out.println("m start"); 17 | while(running) { 18 | /* 19 | try { 20 | TimeUnit.MILLISECONDS.sleep(10); 21 | } catch (InterruptedException e) { 22 | e.printStackTrace(); 23 | }*/ 24 | } 25 | System.out.println("m end!"); 26 | } 27 | 28 | public static void main(String[] args) { 29 | new Thread(T::m, "t1").start(); 30 | 31 | //lambda表达式 new Thread(new Runnable( run() {m()} 32 | 33 | try { 34 | TimeUnit.SECONDS.sleep(1); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | 39 | T.running = false; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_012_Volatile/T03________VolatileReference2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * volatile 引用类型(包括数组)只能保证引用本身的可见性,不能保证内部字段的可见性 3 | */ 4 | package com.mashibing.juc.c_012_Volatile; 5 | 6 | public class T03________VolatileReference2 { 7 | 8 | private static class Data { 9 | int a, b; 10 | 11 | public Data(int a, int b) { 12 | this.a = a; 13 | this.b = b; 14 | } 15 | } 16 | 17 | volatile static Data data; 18 | 19 | public static void main(String[] args) { 20 | Thread writer = new Thread(()->{ 21 | for (int i = 0; i < 10000; i++) { 22 | data = new Data(i, i); 23 | } 24 | }); 25 | 26 | Thread reader = new Thread(()->{ 27 | while (data == null) {} 28 | int x = data.a; 29 | int y = data.b; 30 | if(x != y) { 31 | System.out.printf("a = %s, b=%s%n", x, y); 32 | } 33 | }); 34 | 35 | reader.start(); 36 | writer.start(); 37 | 38 | try { 39 | reader.join(); 40 | writer.join(); 41 | } catch (InterruptedException e) { 42 | e.printStackTrace(); 43 | } 44 | 45 | System.out.println("end"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_012_Volatile/T04_VolatileNotSync.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_012_Volatile/T04_VolatileNotSync.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_012_Volatile/T05_VolatileVsSync.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_012_Volatile/T05_VolatileVsSync.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_016_LockOptimization/FineCoarseLock.java: -------------------------------------------------------------------------------- 1 | /** 2 | * synchronized优化 3 | * 同步代码块中的语句越少越好 4 | * 比较m1和m2 5 | * @author mashibing 6 | */ 7 | package com.mashibing.juc.c_016_LockOptimization; 8 | 9 | import java.util.concurrent.TimeUnit; 10 | 11 | 12 | public class FineCoarseLock { 13 | 14 | int count = 0; 15 | 16 | synchronized void m1() { 17 | //do sth need not sync 18 | try { 19 | TimeUnit.SECONDS.sleep(2); 20 | } catch (InterruptedException e) { 21 | e.printStackTrace(); 22 | } 23 | //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁 24 | count ++; 25 | 26 | //do sth need not sync 27 | try { 28 | TimeUnit.SECONDS.sleep(2); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | void m2() { 35 | //do sth need not sync 36 | try { 37 | TimeUnit.SECONDS.sleep(2); 38 | } catch (InterruptedException e) { 39 | e.printStackTrace(); 40 | } 41 | //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁 42 | //采用细粒度的锁,可以使线程争用时间变短,从而提高效率 43 | synchronized(this) { 44 | count ++; 45 | } 46 | //do sth need not sync 47 | try { 48 | TimeUnit.SECONDS.sleep(2); 49 | } catch (InterruptedException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_017_MoreAboutSync/DoNotLockString.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/DoNotLockString.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_017_MoreAboutSync/SyncSameObject.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/SyncSameObject.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_018_00_AtomicXXX/T01_AtomicInteger.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_018_00_AtomicXXX/T01_AtomicInteger.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_018_00_AtomicXXX/T02_AtomicVsSyncVsLongAdder.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_018_00_AtomicXXX; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | import java.util.concurrent.atomic.AtomicLong; 5 | import java.util.concurrent.atomic.LongAdder; 6 | 7 | public class T02_AtomicVsSyncVsLongAdder { 8 | static long count2 = 0L; 9 | static AtomicLong count1 = new AtomicLong(0L); 10 | static LongAdder count3 = new LongAdder(); 11 | 12 | public static void main(String[] args) throws Exception { 13 | Thread[] threads = new Thread[1000]; 14 | 15 | for(int i=0; i { 18 | for(int k=0; k<100000; k++) count1.incrementAndGet(); 19 | }); 20 | } 21 | 22 | long start = System.currentTimeMillis(); 23 | 24 | for(Thread t : threads ) t.start(); 25 | 26 | for (Thread t : threads) t.join(); 27 | 28 | long end = System.currentTimeMillis(); 29 | 30 | //TimeUnit.SECONDS.sleep(10); 31 | 32 | System.out.println("Atomic: " + count1.get() + " time " + (end-start)); 33 | //----------------------------------------------------------- 34 | Object lock = new Object(); 35 | 36 | for(int i=0; i { 66 | for(int k=0; k<100000; k++) count3.increment(); 67 | }); 68 | } 69 | 70 | start = System.currentTimeMillis(); 71 | 72 | for(Thread t : threads ) t.start(); 73 | 74 | for (Thread t : threads) t.join(); 75 | 76 | end = System.currentTimeMillis(); 77 | 78 | //TimeUnit.SECONDS.sleep(10); 79 | 80 | System.out.println("LongAdder: " + count1.longValue() + " time " + (end-start)); 81 | 82 | } 83 | 84 | static void microSleep(int m) { 85 | try { 86 | TimeUnit.MICROSECONDS.sleep(m); 87 | } catch (InterruptedException e) { 88 | e.printStackTrace(); 89 | } 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_018_00_AtomicXXX/T03________SyncVsLongAdder.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_018_00_AtomicXXX; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | import java.util.concurrent.atomic.LongAdder; 5 | 6 | public class T03________SyncVsLongAdder { 7 | static long count2 = 0L; 8 | static LongAdder count = new LongAdder(); 9 | 10 | public static void main(String[] args) throws Exception { 11 | Thread[] threads = new Thread[500]; 12 | 13 | for(int i=0; i { 16 | for(int k=0; k<100000; k++) count.increment(); 17 | }); 18 | } 19 | 20 | long start = System.currentTimeMillis(); 21 | 22 | for(Thread t : threads ) t.start(); 23 | 24 | for (Thread t : threads) t.join(); 25 | 26 | long end = System.currentTimeMillis(); 27 | 28 | //TimeUnit.SECONDS.sleep(10); 29 | 30 | System.out.println("LongAdder: " + count.longValue() + " time " + (end-start)); 31 | //----------------------------------------------------------- 32 | Object lock = new Object(); 33 | 34 | for(int i=0; i{ 17 | int result = 0; 18 | for(int j=0; j<10000; j++) result += j; 19 | latch.countDown(); 20 | }); 21 | } 22 | 23 | for (int i = 0; i < threads.length; i++) { 24 | threads[i].start(); 25 | } 26 | 27 | try { 28 | latch.await(); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | 33 | System.out.println("end latch"); 34 | } 35 | 36 | private static void usingJoin() { 37 | Thread[] threads = new Thread[100]; 38 | 39 | for(int i=0; i{ 41 | int result = 0; 42 | for(int j=0; j<10000; j++) result += j; 43 | }); 44 | } 45 | 46 | for (int i = 0; i < threads.length; i++) { 47 | threads[i].start(); 48 | } 49 | 50 | for (int i = 0; i < threads.length; i++) { 51 | try { 52 | threads[i].join(); 53 | } catch (InterruptedException e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | 58 | System.out.println("end join"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020/T07_TestCyclicBarrier.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020/T07_TestCyclicBarrier.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020/T08_TestPhaser.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020/T08_TestPhaser.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020/T09_TestPhaser2.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020/T09_TestPhaser2.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020/T10_TestReadWriteLock.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_020; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.atomic.LongAdder; 5 | import java.util.concurrent.locks.Lock; 6 | import java.util.concurrent.locks.ReadWriteLock; 7 | import java.util.concurrent.locks.ReentrantLock; 8 | import java.util.concurrent.locks.ReentrantReadWriteLock; 9 | 10 | public class T10_TestReadWriteLock { 11 | static Lock lock = new ReentrantLock(); 12 | private static int value; 13 | 14 | static ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 15 | static Lock readLock = readWriteLock.readLock(); 16 | static Lock writeLock = readWriteLock.writeLock(); 17 | 18 | public static void read(Lock lock) { 19 | try { 20 | lock.lock(); 21 | Thread.sleep(1000); 22 | System.out.println("read over!"); 23 | //模拟读取操作 24 | } catch (InterruptedException e) { 25 | e.printStackTrace(); 26 | } finally { 27 | lock.unlock(); 28 | } 29 | } 30 | 31 | public static void write(Lock lock, int v) { 32 | try { 33 | lock.lock(); 34 | Thread.sleep(1000); 35 | value = v; 36 | System.out.println("write over!"); 37 | //模拟写操作 38 | } catch (InterruptedException e) { 39 | e.printStackTrace(); 40 | } finally { 41 | lock.unlock(); 42 | } 43 | } 44 | 45 | 46 | 47 | 48 | 49 | public static void main(String[] args) { 50 | //Runnable readR = ()-> read(lock); 51 | Runnable readR = ()-> read(readLock); 52 | 53 | //Runnable writeR = ()->write(lock, new Random().nextInt()); 54 | Runnable writeR = ()->write(writeLock, new Random().nextInt()); 55 | 56 | for(int i=0; i<18; i++) new Thread(readR).start(); 57 | for(int i=0; i<2; i++) new Thread(writeR).start(); 58 | 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020/T11_TestSemaphore.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_020; 2 | 3 | import java.util.concurrent.Semaphore; 4 | 5 | public class T11_TestSemaphore { 6 | public static void main(String[] args) { 7 | //Semaphore s = new Semaphore(2); 8 | Semaphore s = new Semaphore(2, true); 9 | //允许一个线程同时执行 10 | //Semaphore s = new Semaphore(1); 11 | 12 | new Thread(()->{ 13 | try { 14 | s.acquire(); 15 | 16 | System.out.println("T1 running..."); 17 | Thread.sleep(200); 18 | System.out.println("T1 running..."); 19 | 20 | } catch (InterruptedException e) { 21 | e.printStackTrace(); 22 | } finally { 23 | s.release(); 24 | } 25 | }).start(); 26 | 27 | new Thread(()->{ 28 | try { 29 | s.acquire(); 30 | 31 | System.out.println("T2 running..."); 32 | Thread.sleep(200); 33 | System.out.println("T2 running..."); 34 | 35 | s.release(); 36 | } catch (InterruptedException e) { 37 | e.printStackTrace(); 38 | } 39 | }).start(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020/T12_TestExchanger.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_020; 2 | 3 | import java.util.concurrent.Exchanger; 4 | 5 | public class T12_TestExchanger { 6 | 7 | static Exchanger exchanger = new Exchanger<>(); 8 | 9 | public static void main(String[] args) { 10 | new Thread(()->{ 11 | String s = "T1"; 12 | try { 13 | s = exchanger.exchange(s); 14 | } catch (InterruptedException e) { 15 | e.printStackTrace(); 16 | } 17 | System.out.println(Thread.currentThread().getName() + " " + s); 18 | 19 | }, "t1").start(); 20 | 21 | 22 | new Thread(()->{ 23 | String s = "T2"; 24 | try { 25 | s = exchanger.exchange(s); 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | System.out.println(Thread.currentThread().getName() + " " + s); 30 | 31 | }, "t2").start(); 32 | 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020/T13_TestLockSupport.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_020; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | import java.util.concurrent.locks.LockSupport; 5 | 6 | public class T13_TestLockSupport { 7 | public static void main(String[] args) { 8 | Thread t = new Thread(()->{ 9 | for (int i = 0; i < 10; i++) { 10 | System.out.println(i); 11 | if(i == 5) { 12 | LockSupport.park(); 13 | } 14 | try { 15 | TimeUnit.SECONDS.sleep(1); 16 | } catch (InterruptedException e) { 17 | e.printStackTrace(); 18 | } 19 | } 20 | }); 21 | 22 | t.start(); 23 | 24 | LockSupport.unpark(t); 25 | 26 | /*try { 27 | TimeUnit.SECONDS.sleep(8); 28 | } catch (InterruptedException e) { 29 | e.printStackTrace(); 30 | } 31 | System.out.println("after 8 senconds!"); 32 | 33 | LockSupport.unpark(t);*/ 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020_01_Interview/T01_WithoutVolatile.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020_01_Interview/T01_WithoutVolatile.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020_01_Interview/T02_WithVolatile.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020_01_Interview/T02_WithVolatile.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020_01_Interview/T03_NotifyHoldingLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020_01_Interview/T03_NotifyHoldingLock.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020_01_Interview/T04_NotifyFreeLock.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020_01_Interview/T04_NotifyFreeLock.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020_01_Interview/T05_CountDownLatch.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020_01_Interview/T05_CountDownLatch.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020_01_Interview/T06_LockSupport.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020_01_Interview/T06_LockSupport.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020_01_Interview/T07_LockSupport_WithoutSleep.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020_01_Interview/T07_LockSupport_WithoutSleep.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_020_01_Interview/T08_Semaphore.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_020_01_Interview/T08_Semaphore.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer1.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer1.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 面试题:写一个固定容量同步容器,拥有put和get方法,以及getCount方法, 3 | * 能够支持2个生产者线程以及10个消费者线程的阻塞调用 4 | * 5 | * 使用wait和notify/notifyAll来实现 6 | * 7 | * 使用Lock和Condition来实现 8 | * 对比两种方式,Condition的方式可以更加精确的指定哪些线程被唤醒 9 | * 10 | * @author mashibing 11 | */ 12 | package com.mashibing.juc.c_021_01_interview; 13 | 14 | import java.util.LinkedList; 15 | import java.util.concurrent.TimeUnit; 16 | import java.util.concurrent.locks.Condition; 17 | import java.util.concurrent.locks.Lock; 18 | import java.util.concurrent.locks.ReentrantLock; 19 | 20 | public class MyContainer2 { 21 | final private LinkedList lists = new LinkedList<>(); 22 | final private int MAX = 10; //最多10个元素 23 | private int count = 0; 24 | 25 | private Lock lock = new ReentrantLock(); 26 | private Condition producer = lock.newCondition(); 27 | private Condition consumer = lock.newCondition(); 28 | 29 | public void put(T t) { 30 | try { 31 | lock.lock(); 32 | while(lists.size() == MAX) { //想想为什么用while而不是用if? 33 | producer.await(); 34 | } 35 | 36 | lists.add(t); 37 | ++count; 38 | consumer.signalAll(); //通知消费者线程进行消费 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } finally { 42 | lock.unlock(); 43 | } 44 | } 45 | 46 | public T get() { 47 | T t = null; 48 | try { 49 | lock.lock(); 50 | while(lists.size() == 0) { 51 | consumer.await(); 52 | } 53 | t = lists.removeFirst(); 54 | count --; 55 | producer.signalAll(); //通知生产者进行生产 56 | } catch (InterruptedException e) { 57 | e.printStackTrace(); 58 | } finally { 59 | lock.unlock(); 60 | } 61 | return t; 62 | } 63 | 64 | public static void main(String[] args) { 65 | MyContainer2 c = new MyContainer2<>(); 66 | //启动消费者线程 67 | for(int i=0; i<10; i++) { 68 | new Thread(()->{ 69 | for(int j=0; j<5; j++) System.out.println(c.get()); 70 | }, "c" + i).start(); 71 | } 72 | 73 | try { 74 | TimeUnit.SECONDS.sleep(2); 75 | } catch (InterruptedException e) { 76 | e.printStackTrace(); 77 | } 78 | 79 | //启动生产者线程 80 | for(int i=0; i<2; i++) { 81 | new Thread(()->{ 82 | for(int j=0; j<25; j++) c.put(Thread.currentThread().getName() + " " + j); 83 | }, "p" + i).start(); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_021_02_AQS/MLock.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 通过AQS实现自定义锁,目前仅实现了lock和unlock 3 | * @author 马士兵 4 | */ 5 | package com.mashibing.juc.c_021_02_AQS; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | import java.util.concurrent.locks.Condition; 9 | import java.util.concurrent.locks.Lock; 10 | 11 | public class MLock implements Lock { 12 | 13 | private Sync sync = new Sync(); 14 | 15 | @Override 16 | public void lock() { 17 | sync.acquire(1); 18 | } 19 | 20 | @Override 21 | public void unlock() { 22 | sync.release(1); 23 | } 24 | 25 | @Override 26 | public void lockInterruptibly() throws InterruptedException { 27 | 28 | } 29 | 30 | @Override 31 | public boolean tryLock() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { 37 | return false; 38 | } 39 | 40 | @Override 41 | public Condition newCondition() { 42 | return null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_021_02_AQS/Main.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_021_02_AQS; 2 | 3 | import java.util.concurrent.locks.Lock; 4 | 5 | public class Main { 6 | public static int m = 0; 7 | public static Lock lock = new MLock(); 8 | 9 | public static void main(String[] args) throws Exception { 10 | Thread[] threads = new Thread[100]; 11 | 12 | for(int i=0; i{ 14 | try { 15 | lock.lock(); 16 | for (int j = 0; j < 100; j++) m++; 17 | } finally { 18 | lock.unlock(); 19 | } 20 | }); 21 | } 22 | 23 | for(Thread t : threads) t.start(); 24 | 25 | for (Thread t : threads) t.join(); 26 | 27 | System.out.println(m); 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_021_02_AQS/Sync.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_021_02_AQS; 2 | 3 | import java.util.concurrent.locks.AbstractQueuedSynchronizer; 4 | 5 | public class Sync extends AbstractQueuedSynchronizer { 6 | @Override 7 | protected boolean tryAcquire(int arg) { 8 | if(compareAndSetState(0, 1)) { 9 | setExclusiveOwnerThread(Thread.currentThread()); 10 | return true; 11 | } 12 | return false; 13 | } 14 | 15 | @Override 16 | protected boolean tryRelease(int arg) { 17 | setExclusiveOwnerThread(null); 18 | setState(0); 19 | return true; 20 | } 21 | 22 | @Override 23 | protected boolean isHeldExclusively() { 24 | return getState() == 1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_021_02_AQS/TestReentrantLock.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_021_02_AQS; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | public class TestReentrantLock { 6 | 7 | private static volatile int i = 0; 8 | 9 | public static void main(String[] args) { 10 | ReentrantLock lock = new ReentrantLock(); 11 | lock.lock(); 12 | //synchronized (TestReentrantLock.class) { 13 | i++; 14 | //} 15 | 16 | lock.unlock(); 17 | 18 | //synchronized 程序员的丽春院 JUC 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_021_03_VarHandle/T01_HelloVarHandle.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_021_03_VarHandle; 2 | 3 | import java.lang.invoke.MethodHandles; 4 | import java.lang.invoke.VarHandle; 5 | 6 | public class T01_HelloVarHandle { 7 | 8 | int x = 8; 9 | 10 | private static VarHandle handle; 11 | 12 | static { 13 | try { 14 | handle = MethodHandles.lookup().findVarHandle(T01_HelloVarHandle.class, "x", int.class); 15 | } catch (NoSuchFieldException e) { 16 | e.printStackTrace(); 17 | } catch (IllegalAccessException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | 22 | public static void main(String[] args) { 23 | T01_HelloVarHandle t = new T01_HelloVarHandle(); 24 | 25 | //plain read / write 26 | System.out.println((int)handle.get(t)); 27 | handle.set(t,9); 28 | System.out.println(t.x); 29 | 30 | handle.compareAndSet(t, 9, 10); 31 | System.out.println(t.x); 32 | 33 | handle.getAndAdd(t, 10); 34 | System.out.println(t.x); 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/M.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_022_RefTypeAndThreadLocal; 2 | 3 | public class M { 4 | @Override 5 | protected void finalize() throws Throwable { 6 | System.out.println("finalize"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T01_NormalReference.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_022_RefTypeAndThreadLocal; 2 | 3 | import java.io.IOException; 4 | 5 | public class T01_NormalReference { 6 | public static void main(String[] args) throws IOException { 7 | M m = new M(); 8 | m = null; 9 | System.gc(); //DisableExplicitGC 10 | 11 | System.in.read(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T02_SoftReference.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 软引用 3 | * 软引用是用来描述一些还有用但并非必须的对象。 4 | * 对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行第二次回收。 5 | * 如果这次回收还没有足够的内存,才会抛出内存溢出异常。 6 | * -Xmx20M 7 | */ 8 | package com.mashibing.juc.c_022_RefTypeAndThreadLocal; 9 | 10 | import java.lang.ref.SoftReference; 11 | 12 | public class T02_SoftReference { 13 | public static void main(String[] args) { 14 | SoftReference m = new SoftReference<>(new byte[1024*1024*10]); 15 | //m = null; 16 | System.out.println(m.get()); 17 | System.gc(); 18 | try { 19 | Thread.sleep(500); 20 | } catch (InterruptedException e) { 21 | e.printStackTrace(); 22 | } 23 | System.out.println(m.get()); 24 | 25 | //再分配一个数组,heap将装不下,这时候系统会垃圾回收,先回收一次,如果不够,会把软引用干掉 26 | byte[] b = new byte[1024*1024*15]; 27 | System.out.println(m.get()); 28 | } 29 | } 30 | 31 | //软引用非常适合缓存使用 32 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T03_WeakReference.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 弱引用遭到gc就会回收 3 | * 4 | */ 5 | package com.mashibing.juc.c_022_RefTypeAndThreadLocal; 6 | 7 | import java.lang.ref.WeakReference; 8 | 9 | public class T03_WeakReference { 10 | public static void main(String[] args) { 11 | WeakReference m = new WeakReference<>(new M()); 12 | 13 | System.out.println(m.get()); 14 | System.gc(); 15 | System.out.println(m.get()); 16 | 17 | 18 | ThreadLocal tl = new ThreadLocal<>(); 19 | tl.set(new M()); 20 | tl.remove(); 21 | 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T04_PhantomReference.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * 4 | * 一个对象是否有虚引用的存在,完全不会对其生存时间构成影响, 5 | * 也无法通过虚引用来获取一个对象的实例。 6 | * 为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。 7 | * 虚引用和弱引用对关联对象的回收都不会产生影响,如果只有虚引用活着弱引用关联着对象, 8 | * 那么这个对象就会被回收。它们的不同之处在于弱引用的get方法,虚引用的get方法始终返回null, 9 | * 弱引用可以使用ReferenceQueue,虚引用必须配合ReferenceQueue使用。 10 | * 11 | * jdk中直接内存的回收就用到虚引用,由于jvm自动内存管理的范围是堆内存, 12 | * 而直接内存是在堆内存之外(其实是内存映射文件,自行去理解虚拟内存空间的相关概念), 13 | * 所以直接内存的分配和回收都是有Unsafe类去操作,java在申请一块直接内存之后, 14 | * 会在堆内存分配一个对象保存这个堆外内存的引用, 15 | * 这个对象被垃圾收集器管理,一旦这个对象被回收, 16 | * 相应的用户线程会收到通知并对直接内存进行清理工作。 17 | * 18 | * 事实上,虚引用有一个很重要的用途就是用来做堆外内存的释放, 19 | * DirectByteBuffer就是通过虚引用来实现堆外内存的释放的。 20 | * 21 | */ 22 | 23 | 24 | package com.mashibing.juc.c_022_RefTypeAndThreadLocal; 25 | 26 | import java.lang.ref.PhantomReference; 27 | import java.lang.ref.Reference; 28 | import java.lang.ref.ReferenceQueue; 29 | import java.util.LinkedList; 30 | import java.util.List; 31 | 32 | public class T04_PhantomReference { 33 | private static final List LIST = new LinkedList<>(); 34 | private static final ReferenceQueue QUEUE = new ReferenceQueue<>(); 35 | 36 | 37 | 38 | public static void main(String[] args) { 39 | 40 | 41 | PhantomReference phantomReference = new PhantomReference<>(new M(), QUEUE); 42 | 43 | 44 | new Thread(() -> { 45 | while (true) { 46 | LIST.add(new byte[1024 * 1024]); 47 | try { 48 | Thread.sleep(1000); 49 | } catch (InterruptedException e) { 50 | e.printStackTrace(); 51 | Thread.currentThread().interrupt(); 52 | } 53 | System.out.println(phantomReference.get()); 54 | } 55 | }).start(); 56 | 57 | new Thread(() -> { 58 | while (true) { 59 | Reference poll = QUEUE.poll(); 60 | if (poll != null) { 61 | System.out.println("--- 虚引用对象被jvm回收了 ---- " + poll); 62 | } 63 | } 64 | }).start(); 65 | 66 | try { 67 | Thread.sleep(500); 68 | } catch (InterruptedException e) { 69 | e.printStackTrace(); 70 | } 71 | 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal1.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal1.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal2.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal2.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_023/Singleton.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 线程安全的单例模式: 3 | * 4 | * 阅读文章:http://www.cnblogs.com/xudong-bupt/p/3433643.html 5 | * 6 | * 更好的是采用下面的方式,既不用加锁,也能实现懒加载 7 | * 8 | * @author 马士兵 9 | */ 10 | package com.mashibing.juc.c_023; 11 | 12 | import java.util.Arrays; 13 | 14 | public class Singleton { 15 | 16 | private Singleton() { 17 | System.out.println("single"); 18 | } 19 | 20 | private static class Inner { 21 | private static Singleton s = new Singleton(); 22 | } 23 | 24 | public static Singleton getSingle() { 25 | return Inner.s; 26 | } 27 | 28 | public static void main(String[] args) { 29 | Thread[] ths = new Thread[200]; 30 | for(int i=0; i{ 32 | System.out.println(Singleton.getSingle()); 33 | }); 34 | } 35 | 36 | Arrays.asList(ths).forEach(o->o.start()); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_023_01_Containers/HelloQueue.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_023_01_Containers; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.LinkedList; 5 | import java.util.PriorityQueue; 6 | import java.util.Queue; 7 | import java.util.concurrent.ArrayBlockingQueue; 8 | 9 | public class HelloQueue { 10 | public static void main(String[] args) { 11 | Queue q = new ArrayBlockingQueue<>(2); 12 | q.add(0); 13 | q.add(1); 14 | q.add(2); 15 | q.add(3); 16 | System.out.println(q); 17 | 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_023_01_Containers/T01_HelloArray.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_023_01_Containers; 2 | 3 | import java.util.Arrays; 4 | 5 | public class T01_HelloArray { 6 | public static void main(String[] args) { 7 | int[] a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 8 | Arrays.stream(a).map(i->i+1).forEach(i->System.out.print(i + " ")); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_023_01_Containers/T02_CollectionListSetQueue.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_023_01_Containers; 2 | 3 | import java.util.*; 4 | 5 | public class T02_CollectionListSetQueue { 6 | public static void main(String[] args) { 7 | Collection c1 = new ArrayList(); 8 | c1.add(1); 9 | c1.add(2); 10 | c1.add(3); 11 | c1.stream().forEach(System.out::println); 12 | 13 | List c2 = new ArrayList<>(); 14 | Set c3 = new HashSet<>(); 15 | Queue c4 = new LinkedList<>(); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_023_02_FromHashtableToCHM/Constants.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_023_02_FromHashtableToCHM; 2 | 3 | public class Constants { 4 | public static final int COUNT = 1000000; 5 | public static final int THREAD_COUNT = 100; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_023_02_FromHashtableToCHM/T01_TestHashtable.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_023_02_FromHashtableToCHM; 2 | 3 | import java.util.Hashtable; 4 | import java.util.UUID; 5 | 6 | public class T01_TestHashtable { 7 | 8 | static Hashtable m = new Hashtable<>(); 9 | 10 | static int count = Constants.COUNT; 11 | static UUID[] keys = new UUID[count]; 12 | static UUID[] values = new UUID[count]; 13 | static final int THREAD_COUNT = Constants.THREAD_COUNT; 14 | 15 | static { 16 | for (int i = 0; i < count; i++) { 17 | keys[i] = UUID.randomUUID(); 18 | values[i] = UUID.randomUUID(); 19 | } 20 | } 21 | 22 | static class MyThread extends Thread { 23 | int start; 24 | int gap = count/THREAD_COUNT; 25 | 26 | public MyThread(int start) { 27 | this.start = start; 28 | } 29 | 30 | @Override 31 | public void run() { 32 | for(int i=start; i{ 71 | for (int j = 0; j < 10000000; j++) { 72 | m.get(keys[10]); 73 | } 74 | }); 75 | } 76 | 77 | for(Thread t : threads) { 78 | t.start(); 79 | } 80 | 81 | for(Thread t : threads) { 82 | try { 83 | t.join(); 84 | } catch (InterruptedException e) { 85 | e.printStackTrace(); 86 | } 87 | } 88 | 89 | end = System.currentTimeMillis(); 90 | System.out.println(end - start); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_023_02_FromHashtableToCHM/T02_TestHashMap.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_023_02_FromHashtableToCHM; 2 | 3 | import java.util.HashMap; 4 | import java.util.UUID; 5 | 6 | public class T02_TestHashMap { 7 | 8 | static HashMap m = new HashMap<>(); 9 | 10 | static int count = Constants.COUNT; 11 | static UUID[] keys = new UUID[count]; 12 | static UUID[] values = new UUID[count]; 13 | static final int THREAD_COUNT = Constants.THREAD_COUNT; 14 | 15 | static { 16 | for (int i = 0; i < count; i++) { 17 | keys[i] = UUID.randomUUID(); 18 | values[i] = UUID.randomUUID(); 19 | } 20 | } 21 | 22 | static class MyThread extends Thread { 23 | int start; 24 | int gap = count/THREAD_COUNT; 25 | 26 | public MyThread(int start) { 27 | this.start = start; 28 | } 29 | 30 | @Override 31 | public void run() { 32 | for(int i=start; i m = Collections.synchronizedMap(new HashMap()); 11 | 12 | static int count = Constants.COUNT; 13 | static UUID[] keys = new UUID[count]; 14 | static UUID[] values = new UUID[count]; 15 | static final int THREAD_COUNT = Constants.THREAD_COUNT; 16 | 17 | static { 18 | for (int i = 0; i < count; i++) { 19 | keys[i] = UUID.randomUUID(); 20 | values[i] = UUID.randomUUID(); 21 | } 22 | } 23 | 24 | static class MyThread extends Thread { 25 | int start; 26 | int gap = count/THREAD_COUNT; 27 | 28 | public MyThread(int start) { 29 | this.start = start; 30 | } 31 | 32 | @Override 33 | public void run() { 34 | for(int i=start; i{ 73 | for (int j = 0; j < 10000000; j++) { 74 | m.get(keys[10]); 75 | } 76 | }); 77 | } 78 | 79 | for(Thread t : threads) { 80 | t.start(); 81 | } 82 | 83 | for(Thread t : threads) { 84 | try { 85 | t.join(); 86 | } catch (InterruptedException e) { 87 | e.printStackTrace(); 88 | } 89 | } 90 | 91 | end = System.currentTimeMillis(); 92 | System.out.println(end - start); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_023_02_FromHashtableToCHM/T04_TestConcurrentHashMap.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_023_02_FromHashtableToCHM; 2 | 3 | import java.util.Map; 4 | import java.util.UUID; 5 | import java.util.concurrent.ConcurrentHashMap; 6 | 7 | public class T04_TestConcurrentHashMap { 8 | 9 | static Map m = new ConcurrentHashMap<>(); 10 | 11 | static int count = Constants.COUNT; 12 | static UUID[] keys = new UUID[count]; 13 | static UUID[] values = new UUID[count]; 14 | static final int THREAD_COUNT = Constants.THREAD_COUNT; 15 | 16 | static { 17 | for (int i = 0; i < count; i++) { 18 | keys[i] = UUID.randomUUID(); 19 | values[i] = UUID.randomUUID(); 20 | } 21 | } 22 | 23 | static class MyThread extends Thread { 24 | int start; 25 | int gap = count/THREAD_COUNT; 26 | 27 | public MyThread(int start) { 28 | this.start = start; 29 | } 30 | 31 | @Override 32 | public void run() { 33 | for(int i=start; i{ 72 | for (int j = 0; j < 10000000; j++) { 73 | m.get(keys[10]); 74 | } 75 | }); 76 | } 77 | 78 | for(Thread t : threads) { 79 | t.start(); 80 | } 81 | 82 | for(Thread t : threads) { 83 | try { 84 | t.join(); 85 | } catch (InterruptedException e) { 86 | e.printStackTrace(); 87 | } 88 | } 89 | 90 | end = System.currentTimeMillis(); 91 | System.out.println(end - start); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller1.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller1.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller2.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller2.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller3.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller3.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller4.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller4.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/readme.txt: -------------------------------------------------------------------------------- 1 | 同步容器类 2 | 3 | 1:Vector Hashtable :早期使用synchronized实现 4 | 2:ArrayList HashSet :未考虑多线程安全(未实现同步) 5 | 3:HashSet vs Hashtable StringBuilder vs StringBuffer 6 | 4:Collections.synchronized***工厂方法使用的也是synchronized 7 | 8 | 使用早期的同步容器以及Collections.synchronized***方法的不足之处,请阅读: 9 | http://blog.csdn.net/itm_hadf/article/details/7506529 10 | 11 | 使用新的并发容器 12 | http://xuganggogo.iteye.com/blog/321630 13 | 14 | 5: -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T01_ConcurrentMap.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_025/T01_ConcurrentMap.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T02_CopyOnWriteList.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_025/T02_CopyOnWriteList.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T03_SynchronizedList.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_025; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | public class T03_SynchronizedList { 8 | public static void main(String[] args) { 9 | List strs = new ArrayList<>(); 10 | List strsSync = Collections.synchronizedList(strs); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T04_ConcurrentQueue.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_025/T04_ConcurrentQueue.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T05_LinkedBlockingQueue.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_025/T05_LinkedBlockingQueue.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T06_ArrayBlockingQueue.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_025/T06_ArrayBlockingQueue.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T07_01_PriorityQueque.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_025; 2 | 3 | import java.util.PriorityQueue; 4 | 5 | public class T07_01_PriorityQueque { 6 | public static void main(String[] args) { 7 | PriorityQueue q = new PriorityQueue<>(); 8 | 9 | q.add("c"); 10 | q.add("e"); 11 | q.add("a"); 12 | q.add("d"); 13 | q.add("z"); 14 | 15 | for (int i = 0; i < 5; i++) { 16 | System.out.println(q.poll()); 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T07_DelayQueue.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_025; 2 | 3 | import java.util.Calendar; 4 | import java.util.Random; 5 | import java.util.concurrent.BlockingQueue; 6 | import java.util.concurrent.DelayQueue; 7 | import java.util.concurrent.Delayed; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | public class T07_DelayQueue { 11 | 12 | static BlockingQueue tasks = new DelayQueue<>(); 13 | 14 | static Random r = new Random(); 15 | 16 | static class MyTask implements Delayed { 17 | String name; 18 | long runningTime; 19 | 20 | MyTask(String name, long rt) { 21 | this.name = name; 22 | this.runningTime = rt; 23 | } 24 | 25 | @Override 26 | public int compareTo(Delayed o) { 27 | if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)) 28 | return -1; 29 | else if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) 30 | return 1; 31 | else 32 | return 0; 33 | } 34 | 35 | @Override 36 | public long getDelay(TimeUnit unit) { 37 | 38 | return unit.convert(runningTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); 39 | } 40 | 41 | 42 | @Override 43 | public String toString() { 44 | return name + " " + runningTime; 45 | } 46 | } 47 | 48 | public static void main(String[] args) throws InterruptedException { 49 | long now = System.currentTimeMillis(); 50 | MyTask t1 = new MyTask("t1", now + 1000); 51 | MyTask t2 = new MyTask("t2", now + 2000); 52 | MyTask t3 = new MyTask("t3", now + 1500); 53 | MyTask t4 = new MyTask("t4", now + 2500); 54 | MyTask t5 = new MyTask("t5", now + 500); 55 | 56 | tasks.put(t1); 57 | tasks.put(t2); 58 | tasks.put(t3); 59 | tasks.put(t4); 60 | tasks.put(t5); 61 | 62 | System.out.println(tasks); 63 | 64 | for(int i=0; i<5; i++) { 65 | System.out.println(tasks.take()); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T08_SynchronusQueue.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_025/T08_SynchronusQueue.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/T09_TransferQueue.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_025; 2 | 3 | import java.util.concurrent.LinkedTransferQueue; 4 | 5 | public class T09_TransferQueue { 6 | public static void main(String[] args) throws InterruptedException { 7 | LinkedTransferQueue strs = new LinkedTransferQueue<>(); 8 | 9 | new Thread(() -> { 10 | try { 11 | System.out.println(strs.take()); 12 | } catch (InterruptedException e) { 13 | e.printStackTrace(); 14 | } 15 | }).start(); 16 | 17 | strs.transfer("aaa"); 18 | 19 | //strs.put("aaa"); 20 | 21 | 22 | /*new Thread(() -> { 23 | try { 24 | System.out.println(strs.take()); 25 | } catch (InterruptedException e) { 26 | e.printStackTrace(); 27 | } 28 | }).start();*/ 29 | 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_025/readme.txt: -------------------------------------------------------------------------------- 1 | 总结: 2 | 1:对于map/set的选择使用 3 | HashMap 4 | TreeMap 5 | LinkedHashMap 6 | 7 | Hashtable 8 | Collections.sychronizedXXX 9 | 10 | ConcurrentHashMap 11 | ConcurrentSkipListMap 12 | 13 | 2:队列 14 | ArrayList 15 | LinkedList 16 | Collections.synchronizedXXX 17 | CopyOnWriteList 18 | Queue 19 | CocurrentLinkedQueue //concurrentArrayQueue 20 | BlockingQueue 21 | LinkedBQ 22 | ArrayBQ 23 | TransferQueue 24 | SynchronusQueue 25 | DelayQueue执行定时任务 26 | 27 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T01_00_Question.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | public class T01_00_Question { 4 | public static void main(String[] args) { 5 | //要求用线程顺序打印A1B2C3....Z26 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T02_00_LockSupport.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | 4 | import java.util.concurrent.locks.LockSupport; 5 | 6 | //Locksupport park 当前线程阻塞(停止) 7 | //unpark(Thread t) 8 | 9 | public class T02_00_LockSupport { 10 | 11 | 12 | static Thread t1 = null, t2 = null; 13 | 14 | public static void main(String[] args) throws Exception { 15 | char[] aI = "1234567".toCharArray(); 16 | char[] aC = "ABCDEFG".toCharArray(); 17 | 18 | t1 = new Thread(() -> { 19 | 20 | for(char c : aI) { 21 | System.out.print(c); 22 | LockSupport.unpark(t2); //叫醒T2 23 | LockSupport.park(); //T1阻塞 24 | } 25 | 26 | }, "t1"); 27 | 28 | t2 = new Thread(() -> { 29 | 30 | for(char c : aC) { 31 | LockSupport.park(); //t2阻塞 32 | System.out.print(c); 33 | LockSupport.unpark(t1); //叫醒t1 34 | } 35 | 36 | }, "t2"); 37 | 38 | t1.start(); 39 | t2.start(); 40 | } 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T03_00_cas.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | 4 | public class T03_00_cas { 5 | 6 | enum ReadyToRun {T1, T2} 7 | 8 | static volatile ReadyToRun r = ReadyToRun.T1; //思考为什么必须volatile 9 | 10 | public static void main(String[] args) { 11 | 12 | char[] aI = "1234567".toCharArray(); 13 | char[] aC = "ABCDEFG".toCharArray(); 14 | 15 | new Thread(() -> { 16 | 17 | for (char c : aI) { 18 | while (r != ReadyToRun.T1) {} 19 | System.out.print(c); 20 | r = ReadyToRun.T2; 21 | } 22 | 23 | }, "t1").start(); 24 | 25 | new Thread(() -> { 26 | 27 | for (char c : aC) { 28 | while (r != ReadyToRun.T2) {} 29 | System.out.print(c); 30 | r = ReadyToRun.T1; 31 | } 32 | }, "t2").start(); 33 | } 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T04_00_BlockingQueue.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | 4 | import java.util.concurrent.ArrayBlockingQueue; 5 | import java.util.concurrent.BlockingQueue; 6 | import java.util.concurrent.locks.LockSupport; 7 | 8 | public class T04_00_BlockingQueue { 9 | 10 | 11 | static BlockingQueue q1 = new ArrayBlockingQueue(1); 12 | static BlockingQueue q2 = new ArrayBlockingQueue(1); 13 | 14 | public static void main(String[] args) throws Exception { 15 | char[] aI = "1234567".toCharArray(); 16 | char[] aC = "ABCDEFG".toCharArray(); 17 | 18 | new Thread(() -> { 19 | 20 | for(char c : aI) { 21 | System.out.print(c); 22 | try { 23 | q1.put("ok"); 24 | q2.take(); 25 | } catch (InterruptedException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | 30 | }, "t1").start(); 31 | 32 | new Thread(() -> { 33 | 34 | for(char c : aC) { 35 | try { 36 | q1.take(); 37 | } catch (InterruptedException e) { 38 | e.printStackTrace(); 39 | } 40 | System.out.print(c); 41 | try { 42 | q2.put("ok"); 43 | } catch (InterruptedException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | }, "t2").start(); 49 | 50 | 51 | } 52 | } 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T05_00_AtomicInteger.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | public class T05_00_AtomicInteger { 7 | 8 | static AtomicInteger threadNo = new AtomicInteger(1); 9 | 10 | 11 | public static void main(String[] args) { 12 | 13 | char[] aI = "1234567".toCharArray(); 14 | char[] aC = "ABCDEFG".toCharArray(); 15 | 16 | 17 | new Thread(() -> { 18 | 19 | for (char c : aI) { 20 | while (threadNo.get() != 1) {} 21 | System.out.print(c); 22 | threadNo.set(2); 23 | } 24 | 25 | }, "t1").start(); 26 | 27 | new Thread(() -> { 28 | 29 | for (char c : aC) { 30 | while (threadNo.get() != 2) {} 31 | System.out.print(c); 32 | threadNo.set(1); 33 | } 34 | }, "t2").start(); 35 | } 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T06_00_sync_wait_notify.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | 4 | public class T06_00_sync_wait_notify { 5 | public static void main(String[] args) { 6 | final Object o = new Object(); 7 | 8 | char[] aI = "1234567".toCharArray(); 9 | char[] aC = "ABCDEFG".toCharArray(); 10 | 11 | new Thread(()->{ 12 | synchronized (o) { 13 | for(char c : aI) { 14 | System.out.print(c); 15 | try { 16 | o.notify(); 17 | o.wait(); //让出锁 18 | } catch (InterruptedException e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | 23 | o.notify(); //必须,否则无法停止程序 24 | } 25 | 26 | }, "t1").start(); 27 | 28 | new Thread(()->{ 29 | synchronized (o) { 30 | for(char c : aC) { 31 | System.out.print(c); 32 | try { 33 | o.notify(); 34 | o.wait(); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | 40 | o.notify(); 41 | } 42 | }, "t2").start(); 43 | } 44 | } 45 | 46 | //如果我想保证t2在t1之前打印,也就是说保证首先输出的是A而不是1,这个时候该如何做? 47 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T07_00_sync_wait_notify.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | 4 | public class T07_00_sync_wait_notify { 5 | 6 | private static volatile boolean t2Started = false; 7 | 8 | //private static CountDownLatch latch = new C(1); 9 | 10 | public static void main(String[] args) { 11 | final Object o = new Object(); 12 | 13 | 14 | 15 | char[] aI = "1234567".toCharArray(); 16 | char[] aC = "ABCDEFG".toCharArray(); 17 | 18 | new Thread(()->{ 19 | //latch.await(); 20 | 21 | synchronized (o) { 22 | 23 | while(!t2Started) { 24 | try { 25 | o.wait(); 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | 31 | // 32 | 33 | for(char c : aI) { 34 | System.out.print(c); 35 | try { 36 | o.notify(); 37 | o.wait(); 38 | } catch (InterruptedException e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | 43 | o.notify(); 44 | } 45 | }, "t1").start(); 46 | 47 | new Thread(()->{ 48 | 49 | synchronized (o) { 50 | for(char c : aC) { 51 | System.out.print(c); 52 | //latch.countDown() 53 | t2Started = true; 54 | try { 55 | o.notify(); 56 | o.wait(); 57 | } catch (InterruptedException e) { 58 | e.printStackTrace(); 59 | } 60 | } 61 | o.notify(); 62 | } 63 | }, "t2").start(); 64 | } 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T08_00_lock_condition.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | 4 | import java.util.concurrent.locks.Condition; 5 | import java.util.concurrent.locks.Lock; 6 | import java.util.concurrent.locks.ReentrantLock; 7 | 8 | public class T08_00_lock_condition { 9 | 10 | public static void main(String[] args) { 11 | 12 | char[] aI = "1234567".toCharArray(); 13 | char[] aC = "ABCDEFG".toCharArray(); 14 | 15 | Lock lock = new ReentrantLock(); 16 | Condition condition = lock.newCondition(); 17 | 18 | new Thread(()->{ 19 | try { 20 | lock.lock(); 21 | 22 | for(char c : aI) { 23 | System.out.print(c); 24 | condition.signal(); 25 | condition.await(); 26 | } 27 | 28 | condition.signal(); 29 | 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } finally { 33 | lock.unlock(); 34 | } 35 | 36 | }, "t1").start(); 37 | 38 | new Thread(()->{ 39 | try { 40 | lock.lock(); 41 | 42 | for(char c : aC) { 43 | System.out.print(c); 44 | condition.signal(); 45 | condition.await(); 46 | } 47 | 48 | condition.signal(); 49 | 50 | } catch (Exception e) { 51 | e.printStackTrace(); 52 | } finally { 53 | lock.unlock(); 54 | } 55 | 56 | }, "t2").start(); 57 | } 58 | } 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T09_00_lock_condition.java: -------------------------------------------------------------------------------- 1 | /* 2 | Condition本质是锁资源上不同的等待队列 3 | */ 4 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 5 | 6 | 7 | import java.util.concurrent.locks.Condition; 8 | import java.util.concurrent.locks.Lock; 9 | import java.util.concurrent.locks.ReentrantLock; 10 | 11 | public class T09_00_lock_condition { 12 | 13 | public static void main(String[] args) { 14 | 15 | char[] aI = "1234567".toCharArray(); 16 | char[] aC = "ABCDEFG".toCharArray(); 17 | 18 | Lock lock = new ReentrantLock(); 19 | Condition conditionT1 = lock.newCondition(); 20 | Condition conditionT2 = lock.newCondition(); 21 | 22 | new Thread(()->{ 23 | try { 24 | lock.lock(); 25 | 26 | for(char c : aI) { 27 | System.out.print(c); 28 | conditionT2.signal(); 29 | conditionT1.await(); 30 | } 31 | 32 | conditionT2.signal(); 33 | 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | } finally { 37 | lock.unlock(); 38 | } 39 | 40 | }, "t1").start(); 41 | 42 | new Thread(()->{ 43 | try { 44 | lock.lock(); 45 | 46 | for(char c : aC) { 47 | System.out.print(c); 48 | conditionT1.signal(); 49 | conditionT2.await(); 50 | } 51 | 52 | conditionT1.signal(); 53 | 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | } finally { 57 | lock.unlock(); 58 | } 59 | 60 | }, "t2").start(); 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T10_00_PipedStream.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | 4 | import java.io.IOException; 5 | import java.io.PipedInputStream; 6 | import java.io.PipedOutputStream; 7 | 8 | public class T10_00_PipedStream { 9 | 10 | 11 | 12 | 13 | public static void main(String[] args) throws Exception { 14 | char[] aI = "1234567".toCharArray(); 15 | char[] aC = "ABCDEFG".toCharArray(); 16 | 17 | PipedInputStream input1 = new PipedInputStream(); 18 | PipedInputStream input2 = new PipedInputStream(); 19 | PipedOutputStream output1 = new PipedOutputStream(); 20 | PipedOutputStream output2 = new PipedOutputStream(); 21 | 22 | input1.connect(output2); 23 | input2.connect(output1); 24 | 25 | String msg = "Your Turn"; 26 | 27 | 28 | 29 | new Thread(() -> { 30 | 31 | byte[] buffer = new byte[9]; 32 | 33 | try { 34 | for(char c : aI) { 35 | input1.read(buffer); 36 | 37 | if(new String(buffer).equals(msg)) { 38 | System.out.print(c); 39 | } 40 | 41 | output1.write(msg.getBytes()); 42 | } 43 | 44 | } catch (IOException e) { 45 | e.printStackTrace(); 46 | } 47 | 48 | }, "t1").start(); 49 | 50 | new Thread(() -> { 51 | 52 | byte[] buffer = new byte[9]; 53 | 54 | try { 55 | for(char c : aC) { 56 | 57 | System.out.print(c); 58 | 59 | output2.write(msg.getBytes()); 60 | 61 | input2.read(buffer); 62 | 63 | if(new String(buffer).equals(msg)) { 64 | continue; 65 | } 66 | } 67 | 68 | } catch (IOException e) { 69 | e.printStackTrace(); 70 | } 71 | 72 | }, "t2").start(); 73 | } 74 | } 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T12_00_Exchanger_Not_Work.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_00_interview.A1B2C3; 2 | 3 | import java.util.concurrent.Exchanger; 4 | 5 | public class T12_00_Exchanger_Not_Work { 6 | private static Exchanger exchanger = new Exchanger<>(); 7 | 8 | public static void main(String[] args) { 9 | char[] aI = "1234567".toCharArray(); 10 | char[] aC = "ABCDEFG".toCharArray(); 11 | 12 | new Thread(()->{ 13 | for(int i=0; i{ 24 | for(int i=0; i queue = new LinkedTransferQueue(); 12 | new Thread(()->{ 13 | try { 14 | for (char c : aI) { 15 | System.out.print(queue.take()); 16 | queue.transfer(c); 17 | } 18 | 19 | } catch (InterruptedException e) { 20 | e.printStackTrace(); 21 | } 22 | }, "t1").start(); 23 | 24 | new Thread(()->{ 25 | try { 26 | for (char c : aC) { 27 | queue.transfer(c); 28 | System.out.print(queue.take()); 29 | } 30 | 31 | } catch (InterruptedException e) { 32 | e.printStackTrace(); 33 | } 34 | }, "t2").start(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/readme: -------------------------------------------------------------------------------- 1 | 难易程度:LockSupport cas BlockingQueque AtomicInteger sync-wait-notify lock-condition -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T01_MyExecutor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 认识Executor 3 | */ 4 | package com.mashibing.juc.c_026_01_ThreadPool; 5 | 6 | import java.util.concurrent.Executor; 7 | 8 | public class T01_MyExecutor implements Executor{ 9 | 10 | public static void main(String[] args) { 11 | new T01_MyExecutor().execute(()->System.out.println("hello executor")); 12 | } 13 | 14 | @Override 15 | public void execute(Runnable command) { 16 | //new Thread(command).run(); 17 | command.run(); 18 | 19 | } 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T02_ExecutorService.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T02_ExecutorService.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T03_Callable.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T03_Callable.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T04_Executors.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T04_Executors.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T05_00_HelloThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_01_ThreadPool; 2 | 3 | import java.io.IOException; 4 | import java.util.concurrent.*; 5 | 6 | public class T05_00_HelloThreadPool { 7 | 8 | static class Task implements Runnable { 9 | private int i; 10 | 11 | public Task(int i) { 12 | this.i = i; 13 | } 14 | 15 | @Override 16 | public void run() { 17 | System.out.println(Thread.currentThread().getName() + " Task " + i); 18 | try { 19 | System.in.read(); 20 | } catch (IOException e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "Task{" + 28 | "i=" + i + 29 | '}'; 30 | } 31 | } 32 | 33 | public static void main(String[] args) { 34 | ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4, 35 | 60, TimeUnit.SECONDS, 36 | new ArrayBlockingQueue(4), 37 | Executors.defaultThreadFactory(), 38 | new ThreadPoolExecutor.CallerRunsPolicy()); 39 | 40 | for (int i = 0; i < 8; i++) { 41 | tpe.execute(new Task(i)); 42 | } 43 | 44 | System.out.println(tpe.getQueue()); 45 | 46 | tpe.execute(new Task(100)); 47 | 48 | System.out.println(tpe.getQueue()); 49 | 50 | tpe.shutdown(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T05_ThreadPool.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T05_ThreadPool.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_00_Future.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmashibing/JUC/5bd8698269f3880a0734057465efdce86595ddb8/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_00_Future.java -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_01_CompletableFuture.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 假设你能够提供一个服务 3 | * 这个服务查询各大电商网站同一类产品的价格并汇总展示 4 | * @author 马士兵 http://mashibing.com 5 | */ 6 | 7 | package com.mashibing.juc.c_026_01_ThreadPool; 8 | 9 | import java.io.IOException; 10 | import java.util.Random; 11 | import java.util.concurrent.CompletableFuture; 12 | import java.util.concurrent.ExecutionException; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | public class T06_01_CompletableFuture { 16 | public static void main(String[] args) throws ExecutionException, InterruptedException { 17 | long start, end; 18 | 19 | /*start = System.currentTimeMillis(); 20 | 21 | priceOfTM(); 22 | priceOfTB(); 23 | priceOfJD(); 24 | 25 | end = System.currentTimeMillis(); 26 | System.out.println("use serial method call! " + (end - start));*/ 27 | 28 | start = System.currentTimeMillis(); 29 | 30 | CompletableFuture futureTM = CompletableFuture.supplyAsync(()->priceOfTM()); 31 | CompletableFuture futureTB = CompletableFuture.supplyAsync(()->priceOfTB()); 32 | CompletableFuture futureJD = CompletableFuture.supplyAsync(()->priceOfJD()); 33 | 34 | CompletableFuture.allOf(futureTM, futureTB, futureJD).join(); 35 | 36 | CompletableFuture.supplyAsync(()->priceOfTM()) 37 | .thenApply(String::valueOf) 38 | .thenApply(str-> "price " + str) 39 | .thenAccept(System.out::println); 40 | 41 | 42 | end = System.currentTimeMillis(); 43 | System.out.println("use completable future! " + (end - start)); 44 | 45 | try { 46 | System.in.read(); 47 | } catch (IOException e) { 48 | e.printStackTrace(); 49 | } 50 | } 51 | 52 | private static double priceOfTM() { 53 | delay(); 54 | return 1.00; 55 | } 56 | 57 | private static double priceOfTB() { 58 | delay(); 59 | return 2.00; 60 | } 61 | 62 | private static double priceOfJD() { 63 | delay(); 64 | return 3.00; 65 | } 66 | 67 | /*private static double priceOfAmazon() { 68 | delay(); 69 | throw new RuntimeException("product not exist!"); 70 | }*/ 71 | 72 | private static void delay() { 73 | int time = new Random().nextInt(500); 74 | try { 75 | TimeUnit.MILLISECONDS.sleep(time); 76 | } catch (InterruptedException e) { 77 | e.printStackTrace(); 78 | } 79 | System.out.printf("After %s sleep!\n", time); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T07_SingleThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_01_ThreadPool; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class T07_SingleThreadPool { 7 | public static void main(String[] args) { 8 | ExecutorService service = Executors.newSingleThreadExecutor(); 9 | for(int i=0; i<5; i++) { 10 | final int j = i; 11 | service.execute(()->{ 12 | 13 | System.out.println(j + " " + Thread.currentThread().getName()); 14 | }); 15 | } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T08_CachedPool.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_01_ThreadPool; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | public class T08_CachedPool { 8 | public static void main(String[] args) throws InterruptedException { 9 | ExecutorService service = Executors.newCachedThreadPool(); 10 | System.out.println(service); 11 | for (int i = 0; i < 2; i++) { 12 | service.execute(() -> { 13 | try { 14 | TimeUnit.MILLISECONDS.sleep(500); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | System.out.println(Thread.currentThread().getName()); 19 | }); 20 | } 21 | System.out.println(service); 22 | 23 | TimeUnit.SECONDS.sleep(80); 24 | 25 | System.out.println(service); 26 | 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T09_FixedThreadPool.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 线程池的概念 3 | * nasa 4 | */ 5 | package com.mashibing.juc.c_026_01_ThreadPool; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.concurrent.Callable; 10 | import java.util.concurrent.ExecutionException; 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | import java.util.concurrent.Future; 14 | 15 | public class T09_FixedThreadPool { 16 | public static void main(String[] args) throws InterruptedException, ExecutionException { 17 | long start = System.currentTimeMillis(); 18 | getPrime(1, 200000); 19 | long end = System.currentTimeMillis(); 20 | System.out.println(end - start); 21 | 22 | final int cpuCoreNum = 4; 23 | 24 | ExecutorService service = Executors.newFixedThreadPool(cpuCoreNum); 25 | 26 | MyTask t1 = new MyTask(1, 80000); //1-5 5-10 10-15 15-20 27 | MyTask t2 = new MyTask(80001, 130000); 28 | MyTask t3 = new MyTask(130001, 170000); 29 | MyTask t4 = new MyTask(170001, 200000); 30 | 31 | Future> f1 = service.submit(t1); 32 | Future> f2 = service.submit(t2); 33 | Future> f3 = service.submit(t3); 34 | Future> f4 = service.submit(t4); 35 | 36 | start = System.currentTimeMillis(); 37 | f1.get(); 38 | f2.get(); 39 | f3.get(); 40 | f4.get(); 41 | end = System.currentTimeMillis(); 42 | System.out.println(end - start); 43 | } 44 | 45 | static class MyTask implements Callable> { 46 | int startPos, endPos; 47 | 48 | MyTask(int s, int e) { 49 | this.startPos = s; 50 | this.endPos = e; 51 | } 52 | 53 | @Override 54 | public List call() throws Exception { 55 | List r = getPrime(startPos, endPos); 56 | return r; 57 | } 58 | 59 | } 60 | 61 | static boolean isPrime(int num) { 62 | for(int i=2; i<=num/2; i++) { 63 | if(num % i == 0) return false; 64 | } 65 | return true; 66 | } 67 | 68 | static List getPrime(int start, int end) { 69 | List results = new ArrayList<>(); 70 | for(int i=start; i<=end; i++) { 71 | if(isPrime(i)) results.add(i); 72 | } 73 | 74 | return results; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T10_ScheduledPool.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_01_ThreadPool; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.Executors; 5 | import java.util.concurrent.ScheduledExecutorService; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | public class T10_ScheduledPool { 9 | public static void main(String[] args) { 10 | ScheduledExecutorService service = Executors.newScheduledThreadPool(4); 11 | service.scheduleAtFixedRate(()->{ 12 | try { 13 | TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000)); 14 | } catch (InterruptedException e) { 15 | e.printStackTrace(); 16 | } 17 | System.out.println(Thread.currentThread().getName()); 18 | }, 0, 500, TimeUnit.MILLISECONDS); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T11_WorkStealingPool.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.mashibing.juc.c_026_01_ThreadPool; 5 | 6 | import java.io.IOException; 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Executors; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | public class T11_WorkStealingPool { 12 | public static void main(String[] args) throws IOException { 13 | ExecutorService service = Executors.newWorkStealingPool(); 14 | System.out.println(Runtime.getRuntime().availableProcessors()); 15 | 16 | service.execute(new R(1000)); 17 | service.execute(new R(2000)); 18 | service.execute(new R(2000)); 19 | service.execute(new R(2000)); //daemon 20 | service.execute(new R(2000)); 21 | 22 | //由于产生的是精灵线程(守护线程、后台线程),主线程不阻塞的话,看不到输出 23 | System.in.read(); 24 | } 25 | 26 | static class R implements Runnable { 27 | 28 | int time; 29 | 30 | R(int t) { 31 | this.time = t; 32 | } 33 | 34 | @Override 35 | public void run() { 36 | 37 | try { 38 | TimeUnit.MILLISECONDS.sleep(time); 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } 42 | 43 | System.out.println(time + " " + Thread.currentThread().getName()); 44 | 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T12_ForkJoinPool.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_026_01_ThreadPool; 2 | 3 | import java.io.IOException; 4 | import java.util.Arrays; 5 | import java.util.Random; 6 | import java.util.concurrent.ForkJoinPool; 7 | import java.util.concurrent.RecursiveAction; 8 | import java.util.concurrent.RecursiveTask; 9 | 10 | public class T12_ForkJoinPool { 11 | static int[] nums = new int[1000000]; 12 | static final int MAX_NUM = 50000; 13 | static Random r = new Random(); 14 | 15 | static { 16 | for(int i=0; i= s; 40 | } 41 | ``` 42 | 43 | ### 2、构造方法 44 | 45 | ```java 46 | public ThreadPoolExecutor(int corePoolSize, 47 | int maximumPoolSize, 48 | long keepAliveTime, 49 | TimeUnit unit, 50 | BlockingQueue workQueue, 51 | ThreadFactory threadFactory, 52 | RejectedExecutionHandler handler) { 53 | // 基本类型参数校验 54 | if (corePoolSize < 0 || 55 | maximumPoolSize <= 0 || 56 | maximumPoolSize < corePoolSize || 57 | keepAliveTime < 0) 58 | throw new IllegalArgumentException(); 59 | // 空指针校验 60 | if (workQueue == null || threadFactory == null || handler == null) 61 | throw new NullPointerException(); 62 | this.corePoolSize = corePoolSize; 63 | this.maximumPoolSize = maximumPoolSize; 64 | this.workQueue = workQueue; 65 | // 根据传入参数`unit`和`keepAliveTime`,将存活时间转换为纳秒存到变量`keepAliveTime `中 66 | this.keepAliveTime = unit.toNanos(keepAliveTime); 67 | this.threadFactory = threadFactory; 68 | this.handler = handler; 69 | } 70 | ``` 71 | 72 | ### 3、提交执行task的过程 73 | 74 | ```java 75 | public void execute(Runnable command) { 76 | if (command == null) 77 | throw new NullPointerException(); 78 | /* 79 | * Proceed in 3 steps: 80 | * 81 | * 1. If fewer than corePoolSize threads are running, try to 82 | * start a new thread with the given command as its first 83 | * task. The call to addWorker atomically checks runState and 84 | * workerCount, and so prevents false alarms that would add 85 | * threads when it shouldn't, by returning false. 86 | * 87 | * 2. If a task can be successfully queued, then we still need 88 | * to double-check whether we should have added a thread 89 | * (because existing ones died since last checking) or that 90 | * the pool shut down since entry into this method. So we 91 | * recheck state and if necessary roll back the enqueuing if 92 | * stopped, or start a new thread if there are none. 93 | * 94 | * 3. If we cannot queue task, then we try to add a new 95 | * thread. If it fails, we know we are shut down or saturated 96 | * and so reject the task. 97 | */ 98 | int c = ctl.get(); 99 | // worker数量比核心线程数小,直接创建worker执行任务 100 | if (workerCountOf(c) < corePoolSize) { 101 | if (addWorker(command, true)) 102 | return; 103 | c = ctl.get(); 104 | } 105 | // worker数量超过核心线程数,任务直接进入队列 106 | if (isRunning(c) && workQueue.offer(command)) { 107 | int recheck = ctl.get(); 108 | // 线程池状态不是RUNNING状态,说明执行过shutdown命令,需要对新加入的任务执行reject()操作。 109 | // 这儿为什么需要recheck,是因为任务入队列前后,线程池的状态可能会发生变化。 110 | if (! isRunning(recheck) && remove(command)) 111 | reject(command); 112 | // 这儿为什么需要判断0值,主要是在线程池构造方法中,核心线程数允许为0 113 | else if (workerCountOf(recheck) == 0) 114 | addWorker(null, false); 115 | } 116 | // 如果线程池不是运行状态,或者任务进入队列失败,则尝试创建worker执行任务。 117 | // 这儿有3点需要注意: 118 | // 1. 线程池不是运行状态时,addWorker内部会判断线程池状态 119 | // 2. addWorker第2个参数表示是否创建核心线程 120 | // 3. addWorker返回false,则说明任务执行失败,需要执行reject操作 121 | else if (!addWorker(command, false)) 122 | reject(command); 123 | } 124 | ``` 125 | 126 | ### 4、addworker源码解析 127 | 128 | ```java 129 | private boolean addWorker(Runnable firstTask, boolean core) { 130 | retry: 131 | // 外层自旋 132 | for (;;) { 133 | int c = ctl.get(); 134 | int rs = runStateOf(c); 135 | 136 | // 这个条件写得比较难懂,我对其进行了调整,和下面的条件等价 137 | // (rs > SHUTDOWN) || 138 | // (rs == SHUTDOWN && firstTask != null) || 139 | // (rs == SHUTDOWN && workQueue.isEmpty()) 140 | // 1. 线程池状态大于SHUTDOWN时,直接返回false 141 | // 2. 线程池状态等于SHUTDOWN,且firstTask不为null,直接返回false 142 | // 3. 线程池状态等于SHUTDOWN,且队列为空,直接返回false 143 | // Check if queue empty only if necessary. 144 | if (rs >= SHUTDOWN && 145 | ! (rs == SHUTDOWN && 146 | firstTask == null && 147 | ! workQueue.isEmpty())) 148 | return false; 149 | 150 | // 内层自旋 151 | for (;;) { 152 | int wc = workerCountOf(c); 153 | // worker数量超过容量,直接返回false 154 | if (wc >= CAPACITY || 155 | wc >= (core ? corePoolSize : maximumPoolSize)) 156 | return false; 157 | // 使用CAS的方式增加worker数量。 158 | // 若增加成功,则直接跳出外层循环进入到第二部分 159 | if (compareAndIncrementWorkerCount(c)) 160 | break retry; 161 | c = ctl.get(); // Re-read ctl 162 | // 线程池状态发生变化,对外层循环进行自旋 163 | if (runStateOf(c) != rs) 164 | continue retry; 165 | // 其他情况,直接内层循环进行自旋即可 166 | // else CAS failed due to workerCount change; retry inner loop 167 | } 168 | } 169 | boolean workerStarted = false; 170 | boolean workerAdded = false; 171 | Worker w = null; 172 | try { 173 | w = new Worker(firstTask); 174 | final Thread t = w.thread; 175 | if (t != null) { 176 | final ReentrantLock mainLock = this.mainLock; 177 | // worker的添加必须是串行的,因此需要加锁 178 | mainLock.lock(); 179 | try { 180 | // Recheck while holding lock. 181 | // Back out on ThreadFactory failure or if 182 | // shut down before lock acquired. 183 | // 这儿需要重新检查线程池状态 184 | int rs = runStateOf(ctl.get()); 185 | 186 | if (rs < SHUTDOWN || 187 | (rs == SHUTDOWN && firstTask == null)) { 188 | // worker已经调用过了start()方法,则不再创建worker 189 | if (t.isAlive()) // precheck that t is startable 190 | throw new IllegalThreadStateException(); 191 | // worker创建并添加到workers成功 192 | workers.add(w); 193 | // 更新`largestPoolSize`变量 194 | int s = workers.size(); 195 | if (s > largestPoolSize) 196 | largestPoolSize = s; 197 | workerAdded = true; 198 | } 199 | } finally { 200 | mainLock.unlock(); 201 | } 202 | // 启动worker线程 203 | if (workerAdded) { 204 | t.start(); 205 | workerStarted = true; 206 | } 207 | } 208 | } finally { 209 | // worker线程启动失败,说明线程池状态发生了变化(关闭操作被执行),需要进行shutdown相关操作 210 | if (! workerStarted) 211 | addWorkerFailed(w); 212 | } 213 | return workerStarted; 214 | } 215 | ``` 216 | 217 | ### 5、线程池worker任务单元 218 | 219 | ```java 220 | private final class Worker 221 | extends AbstractQueuedSynchronizer 222 | implements Runnable 223 | { 224 | /** 225 | * This class will never be serialized, but we provide a 226 | * serialVersionUID to suppress a javac warning. 227 | */ 228 | private static final long serialVersionUID = 6138294804551838833L; 229 | 230 | /** Thread this worker is running in. Null if factory fails. */ 231 | final Thread thread; 232 | /** Initial task to run. Possibly null. */ 233 | Runnable firstTask; 234 | /** Per-thread task counter */ 235 | volatile long completedTasks; 236 | 237 | /** 238 | * Creates with given first task and thread from ThreadFactory. 239 | * @param firstTask the first task (null if none) 240 | */ 241 | Worker(Runnable firstTask) { 242 | setState(-1); // inhibit interrupts until runWorker 243 | this.firstTask = firstTask; 244 | // 这儿是Worker的关键所在,使用了线程工厂创建了一个线程。传入的参数为当前worker 245 | this.thread = getThreadFactory().newThread(this); 246 | } 247 | 248 | /** Delegates main run loop to outer runWorker */ 249 | public void run() { 250 | runWorker(this); 251 | } 252 | 253 | // 省略代码... 254 | } 255 | ``` 256 | 257 | ### 6、核心线程执行逻辑-runworker 258 | 259 | ```java 260 | final void runWorker(Worker w) { 261 | Thread wt = Thread.currentThread(); 262 | Runnable task = w.firstTask; 263 | w.firstTask = null; 264 | // 调用unlock()是为了让外部可以中断 265 | w.unlock(); // allow interrupts 266 | // 这个变量用于判断是否进入过自旋(while循环) 267 | boolean completedAbruptly = true; 268 | try { 269 | // 这儿是自旋 270 | // 1. 如果firstTask不为null,则执行firstTask; 271 | // 2. 如果firstTask为null,则调用getTask()从队列获取任务。 272 | // 3. 阻塞队列的特性就是:当队列为空时,当前线程会被阻塞等待 273 | while (task != null || (task = getTask()) != null) { 274 | // 这儿对worker进行加锁,是为了达到下面的目的 275 | // 1. 降低锁范围,提升性能 276 | // 2. 保证每个worker执行的任务是串行的 277 | w.lock(); 278 | // If pool is stopping, ensure thread is interrupted; 279 | // if not, ensure thread is not interrupted. This 280 | // requires a recheck in second case to deal with 281 | // shutdownNow race while clearing interrupt 282 | // 如果线程池正在停止,则对当前线程进行中断操作 283 | if ((runStateAtLeast(ctl.get(), STOP) || 284 | (Thread.interrupted() && 285 | runStateAtLeast(ctl.get(), STOP))) && 286 | !wt.isInterrupted()) 287 | wt.interrupt(); 288 | // 执行任务,且在执行前后通过`beforeExecute()`和`afterExecute()`来扩展其功能。 289 | // 这两个方法在当前类里面为空实现。 290 | try { 291 | beforeExecute(wt, task); 292 | Throwable thrown = null; 293 | try { 294 | task.run(); 295 | } catch (RuntimeException x) { 296 | thrown = x; throw x; 297 | } catch (Error x) { 298 | thrown = x; throw x; 299 | } catch (Throwable x) { 300 | thrown = x; throw new Error(x); 301 | } finally { 302 | afterExecute(task, thrown); 303 | } 304 | } finally { 305 | // 帮助gc 306 | task = null; 307 | // 已完成任务数加一 308 | w.completedTasks++; 309 | w.unlock(); 310 | } 311 | } 312 | completedAbruptly = false; 313 | } finally { 314 | // 自旋操作被退出,说明线程池正在结束 315 | processWorkerExit(w, completedAbruptly); 316 | } 317 | } 318 | ``` 319 | 320 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_026_01_ThreadPool/readme.txt: -------------------------------------------------------------------------------- 1 | Executor 2 | ExecutorService submit 3 | Callable = Runnable 4 | Executors 5 | ThreadPool 6 | Future 7 | 8 | fixed cached single scheduled workstealing forkjoin 9 | 10 | ThreadpoolExecutor 11 | 12 | PStreamAPI -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_027_future_to_loom/T01_Future.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 使用future进行异步编程 3 | * 缺点: 4 | * 不知道何时结束 5 | * 阻塞获取结果 6 | */ 7 | 8 | package com.mashibing.juc.c_027_future_to_loom; 9 | 10 | 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | import java.util.concurrent.Future; 14 | 15 | public class T01_Future { 16 | 17 | public static void main(String[] args) throws Exception { 18 | ExecutorService service = Executors.newCachedThreadPool(); 19 | Future future = service.submit(()->{ 20 | return 8; 21 | }); 22 | 23 | int i = future.get(); 24 | 25 | System.out.println(i); 26 | } 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_027_future_to_loom/T02_ListenableFuture.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 代码不好维护 3 | */ 4 | package com.mashibing.juc.c_027_future_to_loom; 5 | 6 | import com.google.common.util.concurrent.*; 7 | import org.checkerframework.checker.nullness.qual.Nullable; 8 | 9 | import java.util.concurrent.Callable; 10 | import java.util.concurrent.Executors; 11 | 12 | public class T02_ListenableFuture { 13 | public static void main(String[] args) { 14 | ListeningExecutorService service = 15 | MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(2)); 16 | ListenableFuture future = service.submit(new Callable() { 17 | @Override 18 | public Integer call() throws Exception { 19 | return 8; 20 | } 21 | }); 22 | 23 | Futures.addCallback(future, new FutureCallback() { 24 | @Override 25 | public void onSuccess(@Nullable Integer integer) { 26 | System.out.println(integer); 27 | } 28 | 29 | @Override 30 | public void onFailure(Throwable throwable) { 31 | throwable.printStackTrace(); 32 | } 33 | }, service); 34 | 35 | service.shutdown(); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_028_FalseSharing/T01_CacheLinePadding.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_028_FalseSharing; 2 | 3 | import java.util.Random; 4 | 5 | public class T01_CacheLinePadding { 6 | private static class T { 7 | public volatile long x = 0L; 8 | } 9 | 10 | public static T[] arr = new T[2]; 11 | 12 | static { 13 | arr[0] = new T(); 14 | arr[1] = new T(); 15 | } 16 | 17 | public static void main(String[] args) throws Exception { 18 | Thread t1 = new Thread(()->{ 19 | for (long i = 0; i < 1000_0000L; i++) { 20 | arr[0].x = i; 21 | } 22 | }); 23 | 24 | Thread t2 = new Thread(()->{ 25 | for (long i = 0; i < 1000_0000L; i++) { 26 | arr[1].x = i; 27 | } 28 | }); 29 | 30 | final long start = System.nanoTime(); 31 | t1.start(); 32 | t2.start(); 33 | t1.join(); 34 | t2.join(); 35 | System.out.println((System.nanoTime() - start)/100_0000); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_028_FalseSharing/T02_CacheLinePadding.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_028_FalseSharing; 2 | 3 | public class T02_CacheLinePadding { 4 | private static class Padding { 5 | public volatile long p1, p2, p3, p4, p5, p6, p7; 6 | } 7 | 8 | private static class T extends Padding { 9 | public volatile long x = 0L; 10 | } 11 | 12 | public static T[] arr = new T[2]; 13 | 14 | static { 15 | arr[0] = new T(); 16 | arr[1] = new T(); 17 | } 18 | 19 | public static void main(String[] args) throws Exception { 20 | Thread t1 = new Thread(()->{ 21 | for (long i = 0; i < 1000_0000L; i++) { 22 | arr[0].x = i; 23 | } 24 | }); 25 | 26 | Thread t2 = new Thread(()->{ 27 | for (long i = 0; i < 1000_0000L; i++) { 28 | arr[1].x = i; 29 | } 30 | }); 31 | 32 | final long start = System.nanoTime(); 33 | t1.start(); 34 | t2.start(); 35 | t1.join(); 36 | t2.join(); 37 | System.out.println((System.nanoTime() - start)/100_0000); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/mashibing/juc/c_029_WriteCombining/WriteCombining.java: -------------------------------------------------------------------------------- 1 | package com.mashibing.juc.c_029_WriteCombining; 2 | 3 | public final class WriteCombining { 4 | 5 | private static final int ITERATIONS = Integer.MAX_VALUE; 6 | private static final int ITEMS = 1 << 24; 7 | private static final int MASK = ITEMS - 1; 8 | 9 | private static final byte[] arrayA = new byte[ITEMS]; 10 | private static final byte[] arrayB = new byte[ITEMS]; 11 | private static final byte[] arrayC = new byte[ITEMS]; 12 | private static final byte[] arrayD = new byte[ITEMS]; 13 | private static final byte[] arrayE = new byte[ITEMS]; 14 | private static final byte[] arrayF = new byte[ITEMS]; 15 | 16 | public static void main(final String[] args) { 17 | 18 | for (int i = 1; i <= 3; i++) { 19 | System.out.println(i + " SingleLoop duration (ns) = " + runCaseOne()); 20 | System.out.println(i + " SplitLoop duration (ns) = " + runCaseTwo()); 21 | } 22 | } 23 | 24 | public static long runCaseOne() { 25 | long start = System.nanoTime(); 26 | int i = ITERATIONS; 27 | 28 | while (--i != 0) { 29 | int slot = i & MASK; 30 | byte b = (byte) i; 31 | arrayA[slot] = b; 32 | arrayB[slot] = b; 33 | arrayC[slot] = b; 34 | arrayD[slot] = b; 35 | arrayE[slot] = b; 36 | arrayF[slot] = b; 37 | } 38 | return System.nanoTime() - start; 39 | } 40 | 41 | public static long runCaseTwo() { 42 | long start = System.nanoTime(); 43 | int i = ITERATIONS; 44 | while (--i != 0) { 45 | int slot = i & MASK; 46 | byte b = (byte) i; 47 | arrayA[slot] = b; 48 | arrayB[slot] = b; 49 | arrayC[slot] = b; 50 | } 51 | i = ITERATIONS; 52 | while (--i != 0) { 53 | int slot = i & MASK; 54 | byte b = (byte) i; 55 | arrayD[slot] = b; 56 | arrayE[slot] = b; 57 | arrayF[slot] = b; 58 | } 59 | return System.nanoTime() - start; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/思考题.txt: -------------------------------------------------------------------------------- 1 | 思考题 2 | 1:A线程正在执行一个对象中的同步方法,B线程是否可以同时执行同一个对象中的非同步方法? 3 | 2:同上,B线程是否可以同时执行同一个对象中的另一个同步方法? 4 | 3:线程抛出异常会释放锁吗? 5 | 4:volatile和synchronized区别? 6 | 5:写一个程序,证明AtomXXX类比synchronized更高效 7 | 6:AtomXXX类可以保证可见性吗?请写一个程序来证明 8 | 7:写一个程序证明AtomXXX类的多个方法并不构成原子性 9 | 8:写一个程序模拟死锁 10 | 9:写一个程序,在main线程中启动100个线程,100个线程完成后,主线程打印“完成”,使用join()和countdownlatch都可以完成,请比较异同。 11 | 10:一个高效的游戏服务器应该如何设计架构? -------------------------------------------------------------------------------- /src/main/resources/Test.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | Alice -> Bob: Authentication Request 3 | Bob --> Alice: Authentication Response 4 | 5 | Alice -> Bob: Another authentication Request 6 | Alice <-- Bob: another authentication Response 7 | @enduml -------------------------------------------------------------------------------- /target/classes/META-INF/JUC.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /target/classes/Test.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | Alice -> Bob: Authentication Request 3 | Bob --> Alice: Authentication Response 4 | 5 | Alice -> Bob: Another authentication Request 6 | Alice <-- Bob: another authentication Response 7 | @enduml --------------------------------------------------------------------------------