2017-05-18 18 views
1

如果我有一個踏板,它計數至1000,並打印出結果,像這樣:無意的線程同步時寫入文件

public class MyRunnable implements Runnable{ 
    @Override 
    public void run() { 
     for (int i=0;i<1000;i++){ 
      System.out.println(i+" "); 
     } 
    } 
} 

而在main我做這樣的事情:

new Thread(new MyRunnable()).start(); 
new Thread(new MyRunnable()).start(); 

的結果混亂起來,因爲我沒有同步。

但是,如果我的線程的樣子:

public class MyRunnable implements Runnable{ 
    Writer w; 
    MyRunnable(Writer w){ 
     this.w=w; 
    } 

    @Override 
    public void run() { 
     for (int i=0;i<1000;i++){ 
      try{ 
       w.write(String.valueOf(i)); 
       w.write (" ") ; 
      }//&catch the exception 
     } 
    } 
} 

和我main我有這樣的:

try (Writer writer = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream("Thread.txt"), "utf-8"))) { 
     Thread t1 =new Thread(new MyRunnable(writer)); 
     Thread t2 =new Thread(new MyRunnable(writer)); 
     t1.start(); 
     t2.start(); 
     t1.join(); 
     t2.join(); 
    } //catch the exception,etc. 

結果看起來正常:線程不知何故同步。我想這是因爲我通過writer作爲參數,但有人可以更好地解釋它嗎?出於好奇,有沒有辦法解決它?

編輯:我的歉意,似乎我匆匆太多了。我試圖簡化MyThread並刪除了太多的代碼。但我只是意識到我描述的情況只會發生,如果我嘗試打開並在run()方法中讀取文件。所以運行其實看起來像這樣:

public void run() { 
    try { 
       Scanner scanner = new Scanner(f); //f is new File (filename) 
       while (scanner.hasNext()) 
       { 
        String str = scanner.next(); 
        if (str.equals("word")) //code counts "word" appearance 
         count++; 
       } 
       scanner.close(); 
      } catch (FileNotFoundException e) { 
       e.printStackTrace(); 
      } 
      for (int i=0;i<1000;i++){ 
       try{ 
        w.write(String.valueOf(i)); 
        w.write (" ") ; 
       }//&catch the exception 
      } //continue by writing the count 

我想這意味着問題實際上是在讀取文件?

+0

硬盤一次只能寫一件東西。因此,如果兩個線程想同時寫入,其中一個線程將不得不等待另一個線程完成。 – litelite

+0

@litelite它是一個'BufferedWriter',它不一定在每次寫入調用時寫入文件。 – matt

+0

你是什麼意思結果將「看起來很正常」,如果我運行精確的測試結果混亂。 – matt

回答

1

這一個將以非同步的方式產生輸出。它與你的相似,所以我認爲你有一些遺漏。

import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.Writer; 
import java.nio.charset.StandardCharsets; 
import java.nio.file.Files; 
import java.nio.file.Paths; 
import java.nio.file.StandardOpenOption; 

/** 
*/ 
public class ThreadTest { 
    final static int N = 1000; 

    static Runnable countDown(Writer writer){ 
     return()->{ 
      for(int i = 0; i<N; i++){ 
       try{ 
        writer.write(String.format("%d\t", i)); 
       } catch(Exception exc){ 

       } 
      } 

      try { 
       writer.write("\n"); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     }; 
    } 

    public static void main(String[] args){ 
     try(
      Writer writer = Files.newBufferedWriter(Paths.get("test.txt"), StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING) 
     ){ 
      Thread a = new Thread(countDown(writer)); 
      Thread b = new Thread(countDown(writer)); 
      a.start(); 
      b.start(); 
      a.join(); 
      b.join(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

    } 

} 

然後輸出變爲:

0 0 1 1 2 2 3 3 4 4 5 6 5 6 7 7 8 8 9 10 9 10 11 11 12 13 12 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27 27 28 28 29 29 30 30 31 32 31 33 32 34 33 35 34 36 37 35 38 36 39 37 40 38 41 39 42 40 43 41 42 44 43 45 44 46 45 47 46 48 47 49 50 48 49 51 50 52 53 51 54 52 55 56 53 57 54 58 55 59 56 60 57 61 58 62 59 63 60 64 61 62 65 63 66 64 67 65 68 66 69 67 70 68 71 69 72 70 73 71 74 72 75 73 76 74 77 75 78 76 77 79 78 80 79 81 80 82 81 83 84 82 85 83 86 84 87 85 88 86 89 87 90 88 91 89 92 90 93 91 94 92 95 93 96 97 94 98 95 99 96 100 97 101 98 102 99 103 100 104 101 105 102 106 103 107 104 108 105 109 106 110 107 111 108 112 109 113 110 114 111 115 112 116 113 117 114 118 115 119 116 120 117 121 118 122 119 123 120 124 121 125 122 126 123 127 124 128 125 129 126 130 127 131 128 132 129 133 130 134 131 135 132 136 133 137 134 138 135 139 136 140 137 141 138 142 139 143 140 144 141 145 142 146 143 147 144 148 145 149 146 150 147 151 148 152 149 153 150 154 151 155 152 156 153 157 154 158 155 159 156 160 157 158 161 162 159 163 160 164 161 165 162 166 163 167 164 168 165 169 166 170 167 171 168 172 169 173 170 174 171 175 172 176 173 177 174 178 175 179 176 180 177 181 178 182 179 183 180 184 181 185 182 186 183 187 184 188 185 189 186 190 187 191 188 192 189 193 190 191 194 192 195 193 196 194 197 195 198 196 199 197 200 198 201 199 202 203 200 204 201 205 202 206 203 207 204 208 209 205 210 206 211 207 212 213 208 214 209 215 210 216 211 217 212 218 213 219 214 220 215 221 216 222 217 223 218 224 219 225 220 226 221 227 222 228 223 229 224 230 225 231 226 232 227 233 234 228 235 236 229 237 230 238 231 239 232 233 240 234 241 235 242 236 243 237 244 238 245 239 246 247 240 241 248 242 249 243 250 244 251 245 252 253 246 247 254 248 255 249 256 250 257 258 251 259 252 253 260 261 254 262 255 256 257 263 258 264 259 265 260 266 261 267 262 268 263 269 264 270 265 271 266 272 267 273 268 274 269 275 270 276 271 277 272 278 273 279 274 280 275 281 276 282 277 283 278 284 279 285 280 286 281 287 282 288 283 289 284 290 285 291 286 292 287 293 288 294 289 295 290 296 291 297 292 298 293 299 294 300 295 301 296 302 297 303 298 304 299 305 300 306 301 307 302 308 303 309 304 310 305 311 306 312 307 313 308 314 309 315 310 316 311 312 317 313 318 314 319 315 320 316 321 317 318 322 323 319 324 320 325 321 326 322 327 323 328 324 329 325 330 326 331 327 332 328 333 329 334 330 335 331 336 332 337 333 338 334 339 335 340 336 341 337 342 338 343 339 344 340 345 341 346 342 347 343 348 344 349 345 350 346 351 347 352 348 353 349 354 350 355 351 352 356 353 357 354 358 355 359 356 360 357 361 358 362 359 363 364 360 365 361 366 362 363 367 364 368 365 369 366 370 367 371 368 372 369 373 370 374 371 375 372 376 373 377 374 378 375 379 376 380 377 381 378 382 379 383 380 384 381 385 382 386 383 387 388 384 389 385 390 386 391 392 387 393 388 394 395 389 396 390 397 398 399 400 391 401 392 402 403 393 404 394 405 406 395 407 408 396 409 397 410 411 398 412 399 413 414 400 415 401 416 417 402 418 403 419 420 404 421 405 422 423 406 424 407 425 426 408 427 409 428 410 429 430 411 431 432 412 433 413 434 414 435 415 436 416 437 417 438 418 439 419 440 420 441 421 442 422 443 423 444 424 445 425 446 426 447 427 448 428 449 429 450 430 451 431 452 432 453 433 454 434 455 435 456 436 457 437 458 438 459 439 460 440 461 441 462 442 463 443 464 444 465 445 466 446 467 447 468 448 469 449 470 450 471 451 472 452 473 453 474 454 475 455 476 456 477 457 478 458 479 480 459 481 482 460 483 484 461 485 486 462 487 463 488 489 464 490 491 465 492 466 493 494 467 495 496 468 497 469 498 499 470 500 501 471 502 472 503 504 473 505 474 506 507 475 508 476 509 510 477 511 478 512 513 479 514 480 515 516 481 517 482 518 519 483 520 484 521 522 523 485 524 486 525 526 487 527 488 528 529 489 530 531 490 532 491 533 492 534 535 493 536 537 494 538 495 539 540 496 541 497 542 543 498 544 499 545 546 500 547 548 501 549 502 550 551 503 552 504 553 554 505 555 506 556 557 507 558 508 559 560 509 561 562 510 563 511 564 565 512 566 513 567 568 514 569 515 570 516 571 572 517 573 518 574 519 575 576 520 577 521 578 579 522 580 581 523 582 524 583 525 584 585 526 586 527 587 588 528 589 529 590 591 530 592 593 531 594 532 595 596 533 597 534 598 599 535 600 536 601 602 537 603 538 604 605 539 606 540 607 541 608 609 542 610 543 611 612 544 613 614 545 615 546 616 617 547 618 548 619 620 549 621 550 622 623 551 624 552 625 626 553 627 554 628 629 555 630 631 556 632 557 633 634 558 635 636 559 637 560 638 639 561 640 641 562 642 563 643 644 564 645 565 646 647 566 648 567 649 650 568 651 652 569 653 654 570 655 571 656 657 572 658 659 573 660 574 661 662 575 663 664 576 665 577 666 667 578 668 579 669 670 580 671 672 581 673 582 674 675 583 676 584 677 678 585 679 680 586 681 682 587 683 684 588 685 589 686 590 687 591 592 688 593 594 689 595 690 596 691 597 692 598 693 599 694 600 695 696 601 697 602 698 603 699 604 700 605 701 606 702 607 703 608 704 609 705 610 706 611 707 612 708 613 709 710 614 711 615 712 616 713 617 714 618 715 619 716 620 717 621 718 622 719 720 623 721 722 624 723 625 724 725 626 726 627 727 728 628 729 629 730 731 630 732 631 733 734 632 735 633 736 737 634 738 635 739 740 636 741 637 742 743 638 744 639 745 746 640 747 641 748 749 642 750 643 751 752 644 753 645 754 755 646 756 647 757 758 648 759 649 760 761 650 762 763 651 764 765 652 766 653 767 768 654 769 655 770 771 656 772 657 773 774 658 775 659 776 777 660 778 661 779 780 662 781 663 782 783 664 784 665 785 786 666 787 788 667 789 668 790 669 791 792 670 793 671 794 795 672 796 673 797 798 674 799 800 675 801 676 802 677 803 804 678 805 806 679 807 808 680 809 681 810 811 682 812 683 813 814 684 815 685 816 817 686 818 687 819 820 688 821 689 822 823 690 824 691 825 826 692 827 693 828 829 694 830 695 831 832 696 833 697 834 835 698 836 699 837 838 700 839 701 840 841 702 842 703 843 704 844 705 845 706 846 707 847 708 848 709 849 710 850 711 851 712 852 853 713 854 714 855 715 856 716 857 717 858 718 859 719 860 720 861 721 862 722 863 723 864 724 865 725 866 726 867 727 868 728 869 729 870 730 871 731 872 732 873 733 874 734 875 735 876 736 877 737 878 738 879 739 880 740 881 741 882 742 883 743 884 744 885 745 886 746 887 747 748 888 889 749 890 891 750 892 893 751 894 895 752 896 753 897 898 754 899 900 755 901 902 756 903 757 904 905 758 906 907 759 908 760 909 910 761 911 912 762 913 914 763 915 916 764 917 765 918 919 766 920 921 767 922 923 768 924 769 925 926 770 927 928 771 929 772 930 931 773 932 774 933 934 775 935 936 776 937 777 938 939 778 940 779 941 780 942 943 781 944 945 782 946 783 947 948 784 949 785 950 951 786 952 787 953 954 788 955 789 956 957 790 958 791 959 960 792 961 793 962 794 963 964 795 965 796 966 797 967 798 968 969 799 970 971 800 972 801 973 974 802 975 976 803 977 804 978 979 805 980 981 806 982 807 983 984 808 809 985 986 810 987 811 988 812 813 989 990 814 991 815 992 816 993 817 818 994 819 995 996 820 997 821 998 822 823 999 
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 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 

其中,你可以看到結束了混亂。

對於您的掃描儀,由於您正在爲Windows上的同一文件製作兩個掃描儀,因此您基本上正在同步該文件。例如。讀/寫狀態結束這樣看:

try{ 
    synchronized(f){ 
     Scanner s = new Scanner(f); 
     System.out.println("starting"); 
     while(s.hasNext()){ 
      System.out.println(s.next().length()); 
     } 
     System.out.println("finished"); 
     s.close(); 
    } 
}catch(Exception e){e.printStackTrace();} 

這樣做的結果是,一個線程讀取該文件,結束和開始計數,在這一點上,其他線程開始讀取文件。讀取文件需要比倒計時更長的時間。

+0

是的,我只是編輯了這個問題 - 我忽略了在運行()中讀取文件的事實。這可能是同步的原因? – murksiuke

+0

@murksiuke我編輯我的示例以顯示行爲就像掃描儀是同步的。 – matt

+0

非常感謝你,我感謝你的幫助 – murksiuke

2

write(String)方法Writer(其中BufferedWriter延伸自)被同步。

+0

因此,每個要寫入的調用應該是同步的,但OP正在進行許多獨立調用。它是'synchronized(obj){for(...){// do stuff}}'之間的區別,它會給出輸出op描述與OP正在做的事情,看起來像'for(...){ synchronized(obj){// do stuff}}'在這種情況下,一個線程可能會丟失鎖定並寫入亂序。 – matt

0

目前尚不清楚你想要什麼。但是如果你只是想讓t1和t2混淆他們的數字,你應該確保它們同時開始。一個簡單的方法來做到這一點是使用您在線程存儲這樣的CountDownLatch:

public class MyRunnable implements Runnable{ 
     Writer w; 
     CountDownLatch countDownLatch; 
     MyRunnable(Writer w, CountDownLatch countDownLatch){ 
      this.w=w; 
      this.countDownLatch=countDownLatch; 
     } 

     @Override 
     public void run() { 
      countDownLatch.await(); 
      for (int i=0;i<1000;i++){ 
       try{ 
        w.write(String.valueOf(i)); 
        w.write (" ") ; 
       }//&catch the exception 
      } 
     } 
} 

而且你的線程之前創建並啓動在創建時:

try (Writer writer = new BufferedWriter(new OutputStreamWriter(
     new FileOutputStream("Thread.txt"), "utf-8"))) { 
    CountDownLatch countDownLatch = new CountDownLatch(1); 
    Thread t1 =new Thread(new MyRunnable(writer, countDownLatch)); 
    Thread t2 =new Thread(new MyRunnable(writer), countDownLatch); 
    t1.start(); 
    t2.start(); 
    countDownLatch.countDown(); //Start the threads 
    t1.join(); 
    t2.join(); 
} //catch the exception,etc. 

這將確保創建線程所用的時間不會影響您的測試,並確保兩個線程實際同時啓動。