复习多线程进阶

本文深入探讨了Java中的Lambda表达式,强调其作为函数式接口简化代码的作用。接着,通过静态代理模式展示了如何模拟婚庆公司,解释了线程的生命周期和停止、休眠、礼让及强制执行等状态。此外,还讲解了线程的优先级、守护线程和线程同步的概念,以及死锁的产生条件。最后,通过示例展示了线程同步在解决并发问题中的应用。
摘要由CSDN通过智能技术生成

目录

Lamda表达式 :

为什么使用Lambda表达式

静态代理模式 : (婚庆公司)

线程状态 :

 停止线程 (Stop) : 

线程休眠 (Sleep) : 

线程礼让 (Yield) : 

线程强制执行 (Join):

线程状态观测 (State) : 

线程优先级 (Priority) :

守护(daemon)线程

线程同步 : 

死锁 : 


Lamda表达式 :

  • 理解Functional Interface(函数式接口) 是学习Java8 lambda表达式的关键所在
  • 函数式接口的定义: 
    • 任何接口, 如果只包含唯一一个抽象方法, 那么它就是一个函数式接口
      • public interface Runnable{ public abstract void run(); }
    • 对于函数式接口, 我们可以通过lambda表达式来创建该接口的对象
/*
* 推导lambda表达式
* */

public class TestLambda01 {

    //3. 静态内部类
    static class Like2 implements ILike{
        @Override
        public void lambda() {
            System.out.println("i like lambda2");
        }
    }

    public static void main(String[] args) {
        ILike like = new Like();
        like.lambda();
        like = new Like2();
        like.lambda();

        //4. 局部内部类
        class Like3 implements ILike{
            @Override
            public void lambda() {
                System.out.println("i like lambda3");
            }
        }
        like = new Like3();
        like.lambda();

        //5. 匿名内部类, 没有类的名称, 必须借助接口或者父类
        like = new ILike() {
            @Override
            public void lambda() {
                System.out.println("i like lambda4");
            }
        };
        like.lambda();

        //6. 用lambda简化
        like=()->{
            System.out.println("i like lambda5");
        };
        like.lambda();
    }
}
//1. 定义一个函数式接口
interface ILike{
    void lambda();
}
//2. 实现类
class Like implements ILike{
    @Override
    public void lambda() {
        System.out.println("i like lambda");
    }
}

为什么使用Lambda表达式

  • 避免内部类定义过多
  • 可以让代码看起来简洁
  • 去掉了一堆没有意义的代码, 只留下核心逻辑

 简化代码如下 :

public class TestLambda02 {
    public static void main(String[] args) {
//        ILove love = new Love();
//        love.love(2);
        ILove love = a->System.out.println("i love you-->" + a);
        love.love(520);
    }
}
interface ILove{
    void love(int a);
}
//class Love implements ILove{
//    @Override
//    public void love(int a) {
//        System.out.println("i love you-->" + a);
//    }
//}

静态代理模式 : (婚庆公司)

  • 真实对象和代理对象都要实现同一个接口
  • 代理对象要代理真实角色
  • 代理对象可以做很多真实对象做不了的事情
  • 真实对象可以专注做自己的事情
public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();//你要结婚
        WeddingCompany weddingCompany = new WeddingCompany(you);//给婚庆公司
        weddingCompany.HappyMarry();//婚庆公司代理执行
    }

}
interface Marry{
    void HappyMarry();
}
//真实角色, 我结婚
class You implements Marry{
    @Override
    public void HappyMarry() {
        System.out.println("我要结婚了, 超开心! ");
    }
}
//代理角色, 帮助我结婚
class WeddingCompany implements Marry{
    //代理谁-->真实目标角色
    private Marry taget;
    public WeddingCompany(Marry taget){
        this.taget = taget;
    }
    @Override
    public void HappyMarry() {
        before();
        this.taget.HappyMarry();//真实对象
        after();
    }

    private void after() {
        System.out.println("结婚之后收拾垃圾");
    }

    private void before() {
        System.out.println("结婚之前布置会场");
    }
}

理解Runnable和Thread的关系

new Thread( ()-> System.out.println("我爱你") ).start();

new WeddingCompany(new You()).HappyMarry();

观察上面两个表达式可知, Thread继承了Runnable接口, 给指定对象,使用start方法.

线程状态 :

 停止线程 (Stop) : 

  • 不推荐使用JDK提供的stop(), destory()方法 [已废弃]
  • 推荐线程自己停止下来
  • 建议使用一个标志位进行终止变量, 当flag=false, 则终止线程运行
//测试stop
// 1. 建议线程正常停止--->利用次数, 不建议死循环
// 2. 建议使用标志位--->设置一个标志位
// 3. 不要使用stop或者destroy等过时或者JDK不建议使用的方法

public class TestStop implements Runnable {
    // 1. 设置一个标识位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag){
            System.out.println("线程正在运行" + i++);
        }
    }

    // 2. 设置一个公开的方法停止线程, 转换标志位

    public void stop(){
        this.flag = false;
    }

    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();

        for (int i=0;i<1000;i++){
            System.out.println("main"+i);
            if (i==900){
                //调用stop方法切换标志位, 让线程停止
                testStop.stop();
                System.out.println("线程该停止了");
            }
        }
    }

}
结果:(主线程运行到900,进程结束,主线程继续运行)
main0
main1
main2
main3
main4
main5
main6
main7
main8
main9
main10
main11
main12
main13
main14
main15
main16
main17
main18
main19
main20
线程正在运行0
main21
线程正在运行1
线程正在运行2
main22
main23
main24
main25
main26
main27
main28
main29
main30
main31
main32
main33
main34
main35
main36
main37
main38
main39
main40
main41
main42
main43
main44
main45
main46
main47
main48
main49
main50
main51
main52
main53
main54
线程正在运行3
线程正在运行4
main55
线程正在运行5
线程正在运行6
main56
main57
main58
main59
main60
main61
main62
main63
main64
线程正在运行7
main65
main66
main67
main68
main69
main70
main71
main72
main73
main74
main75
main76
main77
main78
main79
main80
main81
main82
main83
main84
main85
main86
main87
main88
main89
main90
main91
main92
main93
main94
main95
main96
main97
main98
main99
main100
线程正在运行8
main101
线程正在运行9
main102
main103
main104
main105
main106
main107
main108
main109
线程正在运行10
线程正在运行11
main110
线程正在运行12
main111
线程正在运行13
main112
线程正在运行14
main113
线程正在运行15
main114
线程正在运行16
main115
线程正在运行17
main116
线程正在运行18
main117
线程正在运行19
main118
main119
main120
main121
main122
main123
main124
main125
main126
main127
main128
main129
main130
main131
main132
main133
main134
main135
main136
main137
main138
main139
main140
main141
main142
main143
main144
main145
main146
main147
main148
main149
main150
main151
main152
main153
main154
main155
main156
main157
main158
main159
main160
main161
main162
main163
main164
main165
main166
main167
main168
main169
main170
main171
线程正在运行20
main172
main173
线程正在运行21
main174
线程正在运行22
main175
线程正在运行23
main176
线程正在运行24
main177
线程正在运行25
main178
线程正在运行26
main179
线程正在运行27
main180
线程正在运行28
main181
线程正在运行29
main182
线程正在运行30
main183
线程正在运行31
main184
线程正在运行32
main185
线程正在运行33
main186
线程正在运行34
main187
main188
main189
线程正在运行35
线程正在运行36
线程正在运行37
线程正在运行38
线程正在运行39
线程正在运行40
线程正在运行41
main190
线程正在运行42
线程正在运行43
线程正在运行44
线程正在运行45
线程正在运行46
线程正在运行47
线程正在运行48
线程正在运行49
线程正在运行50
线程正在运行51
线程正在运行52
线程正在运行53
线程正在运行54
线程正在运行55
main191
main192
线程正在运行56
main193
线程正在运行57
线程正在运行58
main194
线程正在运行59
main195
线程正在运行60
main196
线程正在运行61
main197
线程正在运行62
main198
线程正在运行63
main199
线程正在运行64
main200
线程正在运行65
main201
main202
main203
main204
main205
main206
main207
main208
main209
main210
main211
main212
main213
main214
main215
线程正在运行66
main216
线程正在运行67
线程正在运行68
main217
线程正在运行69
main218
线程正在运行70
main219
线程正在运行71
线程正在运行72
main220
main221
线程正在运行73
main222
main223
线程正在运行74
main224
线程正在运行75
main225
线程正在运行76
main226
main227
线程正在运行77
线程正在运行78
线程正在运行79
线程正在运行80
main228
main229
main230
main231
main232
main233
main234
main235
main236
main237
main238
main239
main240
main241
main242
main243
main244
main245
main246
main247
main248
main249
main250
main251
main252
main253
main254
main255
main256
main257
main258
main259
main260
线程正在运行81
main261
main262
main263
main264
main265
main266
main267
main268
main269
main270
main271
main272
main273
main274
线程正在运行82
main275
main276
main277
main278
main279
线程正在运行83
main280
main281
main282
main283
main284
main285
main286
main287
main288
main289
main290
线程正在运行84
main291
线程正在运行85
main292
线程正在运行86
main293
线程正在运行87
main294
线程正在运行88
main295
main296
main297
线程正在运行89
main298
线程正在运行90
main299
main300
main301
main302
main303
main304
main305
main306
main307
main308
main309
main310
main311
main312
main313
main314
main315
main316
main317
main318
main319
main320
main321
main322
main323
main324
main325
main326
main327
main328
main329
main330
main331
main332
main333
main334
main335
main336
main337
main338
main339
main340
main341
main342
main343
main344
main345
main346
main347
main348
main349
main350
main351
main352
main353
main354
main355
main356
main357
main358
main359
main360
main361
main362
main363
main364
main365
main366
main367
main368
main369
main370
线程正在运行91
main371
线程正在运行92
main372
main373
main374
main375
main376
main377
main378
main379
main380
main381
main382
main383
main384
main385
main386
main387
main388
main389
main390
main391
main392
main393
main394
main395
main396
线程正在运行93
main397
main398
main399
main400
main401
main402
main403
main404
main405
main406
main407
线程正在运行94
main408
线程正在运行95
main409
线程正在运行96
main410
线程正在运行97
main411
线程正在运行98
main412
main413
main414
main415
main416
线程正在运行99
main417
线程正在运行100
main418
线程正在运行101
main419
线程正在运行102
main420
main421
main422
main423
main424
main425
线程正在运行103
线程正在运行104
线程正在运行105
线程正在运行106
线程正在运行107
线程正在运行108
线程正在运行109
线程正在运行110
线程正在运行111
main426
线程正在运行112
main427
线程正在运行113
main428
线程正在运行114
main429
线程正在运行115
main430
线程正在运行116
main431
线程正在运行117
main432
线程正在运行118
main433
线程正在运行119
线程正在运行120
线程正在运行121
线程正在运行122
main434
线程正在运行123
线程正在运行124
线程正在运行125
线程正在运行126
线程正在运行127
线程正在运行128
线程正在运行129
线程正在运行130
线程正在运行131
线程正在运行132
线程正在运行133
线程正在运行134
线程正在运行135
main435
线程正在运行136
main436
线程正在运行137
main437
线程正在运行138
main438
线程正在运行139
main439
线程正在运行140
main440
线程正在运行141
main441
线程正在运行142
main442
main443
main444
main445
线程正在运行143
main446
线程正在运行144
main447
线程正在运行145
main448
线程正在运行146
main449
线程正在运行147
main450
线程正在运行148
线程正在运行149
线程正在运行150
线程正在运行151
线程正在运行152
线程正在运行153
线程正在运行154
线程正在运行155
线程正在运行156
线程正在运行157
线程正在运行158
线程正在运行159
线程正在运行160
线程正在运行161
线程正在运行162
线程正在运行163
线程正在运行164
线程正在运行165
线程正在运行166
线程正在运行167
线程正在运行168
线程正在运行169
线程正在运行170
线程正在运行171
线程正在运行172
线程正在运行173
线程正在运行174
线程正在运行175
线程正在运行176
线程正在运行177
线程正在运行178
线程正在运行179
线程正在运行180
线程正在运行181
线程正在运行182
线程正在运行183
线程正在运行184
线程正在运行185
线程正在运行186
线程正在运行187
线程正在运行188
线程正在运行189
线程正在运行190
线程正在运行191
线程正在运行192
线程正在运行193
线程正在运行194
线程正在运行195
线程正在运行196
线程正在运行197
线程正在运行198
线程正在运行199
线程正在运行200
线程正在运行201
线程正在运行202
线程正在运行203
线程正在运行204
线程正在运行205
线程正在运行206
线程正在运行207
线程正在运行208
线程正在运行209
线程正在运行210
线程正在运行211
线程正在运行212
线程正在运行213
线程正在运行214
线程正在运行215
线程正在运行216
线程正在运行217
线程正在运行218
线程正在运行219
线程正在运行220
线程正在运行221
线程正在运行222
线程正在运行223
线程正在运行224
线程正在运行225
线程正在运行226
线程正在运行227
线程正在运行228
线程正在运行229
线程正在运行230
线程正在运行231
线程正在运行232
线程正在运行233
线程正在运行234
线程正在运行235
线程正在运行236
线程正在运行237
线程正在运行238
线程正在运行239
线程正在运行240
线程正在运行241
线程正在运行242
线程正在运行243
线程正在运行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
线程正在运行282
线程正在运行283
线程正在运行284
线程正在运行285
线程正在运行286
线程正在运行287
线程正在运行288
线程正在运行289
线程正在运行290
线程正在运行291
线程正在运行292
线程正在运行293
线程正在运行294
线程正在运行295
线程正在运行296
线程正在运行297
线程正在运行298
线程正在运行299
线程正在运行300
线程正在运行301
线程正在运行302
线程正在运行303
线程正在运行304
线程正在运行305
线程正在运行306
线程正在运行307
线程正在运行308
线程正在运行309
线程正在运行310
线程正在运行311
线程正在运行312
线程正在运行313
线程正在运行314
线程正在运行315
线程正在运行316
线程正在运行317
线程正在运行318
线程正在运行319
main451
线程正在运行320
线程正在运行321
线程正在运行322
线程正在运行323
线程正在运行324
线程正在运行325
线程正在运行326
线程正在运行327
线程正在运行328
线程正在运行329
线程正在运行330
线程正在运行331
线程正在运行332
线程正在运行333
线程正在运行334
线程正在运行335
线程正在运行336
线程正在运行337
main452
线程正在运行338
线程正在运行339
线程正在运行340
线程正在运行341
线程正在运行342
线程正在运行343
线程正在运行344
线程正在运行345
线程正在运行346
线程正在运行347
线程正在运行348
线程正在运行349
线程正在运行350
线程正在运行351
main453
线程正在运行352
线程正在运行353
线程正在运行354
线程正在运行355
线程正在运行356
线程正在运行357
线程正在运行358
线程正在运行359
线程正在运行360
线程正在运行361
线程正在运行362
线程正在运行363
线程正在运行364
线程正在运行365
线程正在运行366
线程正在运行367
线程正在运行368
线程正在运行369
线程正在运行370
线程正在运行371
线程正在运行372
线程正在运行373
线程正在运行374
线程正在运行375
线程正在运行376
线程正在运行377
线程正在运行378
线程正在运行379
线程正在运行380
线程正在运行381
线程正在运行382
线程正在运行383
线程正在运行384
线程正在运行385
线程正在运行386
main454
main455
main456
main457
main458
main459
main460
main461
main462
main463
main464
main465
main466
main467
main468
main469
main470
main471
main472
main473
main474
main475
main476
main477
main478
main479
main480
线程正在运行387
main481
main482
main483
main484
main485
main486
main487
main488
main489
main490
main491
main492
main493
线程正在运行388
main494
线程正在运行389
main495
线程正在运行390
main496
线程正在运行391
线程正在运行392
线程正在运行393
线程正在运行394
线程正在运行395
线程正在运行396
main497
线程正在运行397
main498
线程正在运行398
main499
main500
线程正在运行399
线程正在运行400
main501
main502
main503
main504
main505
main506
main507
main508
main509
main510
main511
main512
main513
main514
main515
main516
main517
main518
main519
main520
main521
main522
main523
main524
main525
main526
main527
main528
main529
main530
main531
main532
main533
main534
main535
main536
main537
main538
main539
main540
线程正在运行401
线程正在运行402
线程正在运行403
线程正在运行404
main541
线程正在运行405
线程正在运行406
线程正在运行407
线程正在运行408
线程正在运行409
线程正在运行410
线程正在运行411
线程正在运行412
线程正在运行413
线程正在运行414
线程正在运行415
线程正在运行416
线程正在运行417
线程正在运行418
线程正在运行419
线程正在运行420
线程正在运行421
线程正在运行422
线程正在运行423
线程正在运行424
线程正在运行425
线程正在运行426
线程正在运行427
线程正在运行428
线程正在运行429
线程正在运行430
线程正在运行431
线程正在运行432
线程正在运行433
线程正在运行434
线程正在运行435
线程正在运行436
main542
main543
main544
main545
线程正在运行437
线程正在运行438
线程正在运行439
main546
线程正在运行440
线程正在运行441
线程正在运行442
线程正在运行443
线程正在运行444
线程正在运行445
线程正在运行446
线程正在运行447
线程正在运行448
线程正在运行449
线程正在运行450
线程正在运行451
线程正在运行452
线程正在运行453
线程正在运行454
线程正在运行455
线程正在运行456
线程正在运行457
线程正在运行458
main547
main548
main549
main550
main551
main552
main553
main554
线程正在运行459
main555
main556
main557
main558
main559
main560
main561
main562
main563
main564
线程正在运行460
main565
main566
线程正在运行461
线程正在运行462
main567
线程正在运行463
main568
线程正在运行464
线程正在运行465
线程正在运行466
线程正在运行467
线程正在运行468
线程正在运行469
线程正在运行470
线程正在运行471
线程正在运行472
线程正在运行473
线程正在运行474
线程正在运行475
线程正在运行476
线程正在运行477
线程正在运行478
线程正在运行479
线程正在运行480
线程正在运行481
线程正在运行482
线程正在运行483
线程正在运行484
main569
main570
main571
main572
main573
main574
main575
main576
main577
main578
main579
main580
main581
main582
main583
main584
main585
main586
main587
main588
main589
main590
main591
main592
main593
main594
main595
main596
main597
main598
main599
main600
main601
main602
main603
main604
main605
main606
main607
main608
main609
main610
main611
main612
main613
main614
main615
main616
main617
main618
main619
main620
main621
main622
main623
main624
main625
main626
main627
main628
main629
main630
main631
main632
main633
main634
main635
main636
main637
main638
main639
main640
main641
main642
main643
main644
main645
main646
main647
main648
main649
main650
main651
main652
main653
线程正在运行485
main654
main655
main656
main657
main658
main659
main660
main661
main662
main663
线程正在运行486
main664
main665
main666
main667
main668
main669
main670
main671
main672
main673
main674
main675
main676
main677
main678
main679
main680
线程正在运行487
线程正在运行488
线程正在运行489
线程正在运行490
线程正在运行491
线程正在运行492
线程正在运行493
线程正在运行494
线程正在运行495
线程正在运行496
线程正在运行497
线程正在运行498
线程正在运行499
线程正在运行500
线程正在运行501
线程正在运行502
线程正在运行503
线程正在运行504
线程正在运行505
线程正在运行506
线程正在运行507
线程正在运行508
线程正在运行509
线程正在运行510
线程正在运行511
线程正在运行512
main681
线程正在运行513
main682
线程正在运行514
线程正在运行515
线程正在运行516
线程正在运行517
线程正在运行518
线程正在运行519
线程正在运行520
线程正在运行521
线程正在运行522
线程正在运行523
线程正在运行524
线程正在运行525
线程正在运行526
线程正在运行527
线程正在运行528
线程正在运行529
线程正在运行530
线程正在运行531
线程正在运行532
线程正在运行533
线程正在运行534
线程正在运行535
线程正在运行536
线程正在运行537
线程正在运行538
线程正在运行539
线程正在运行540
线程正在运行541
线程正在运行542
线程正在运行543
线程正在运行544
线程正在运行545
main683
main684
main685
main686
main687
main688
main689
main690
main691
main692
main693
main694
main695
main696
main697
main698
main699
main700
main701
main702
main703
main704
main705
main706
main707
main708
main709
main710
main711
main712
main713
main714
main715
main716
main717
main718
main719
main720
main721
main722
main723
main724
main725
main726
main727
main728
main729
main730
main731
main732
main733
main734
main735
main736
main737
main738
main739
main740
main741
main742
main743
main744
main745
main746
main747
main748
main749
main750
main751
main752
main753
main754
线程正在运行546
main755
main756
main757
main758
main759
main760
main761
线程正在运行547
线程正在运行548
线程正在运行549
线程正在运行550
线程正在运行551
线程正在运行552
线程正在运行553
线程正在运行554
线程正在运行555
线程正在运行556
线程正在运行557
线程正在运行558
线程正在运行559
线程正在运行560
线程正在运行561
线程正在运行562
线程正在运行563
main762
线程正在运行564
线程正在运行565
线程正在运行566
线程正在运行567
线程正在运行568
线程正在运行569
线程正在运行570
线程正在运行571
线程正在运行572
线程正在运行573
线程正在运行574
线程正在运行575
线程正在运行576
线程正在运行577
线程正在运行578
线程正在运行579
线程正在运行580
main763
main764
main765
main766
main767
main768
main769
main770
main771
main772
main773
main774
main775
main776
main777
main778
main779
main780
main781
main782
main783
main784
main785
main786
main787
main788
main789
main790
main791
线程正在运行581
线程正在运行582
线程正在运行583
线程正在运行584
线程正在运行585
线程正在运行586
线程正在运行587
线程正在运行588
线程正在运行589
线程正在运行590
线程正在运行591
线程正在运行592
线程正在运行593
线程正在运行594
线程正在运行595
线程正在运行596
线程正在运行597
线程正在运行598
main792
main793
main794
main795
main796
main797
main798
main799
main800
main801
main802
main803
main804
main805
main806
main807
main808
main809
线程正在运行599
线程正在运行600
线程正在运行601
线程正在运行602
线程正在运行603
线程正在运行604
线程正在运行605
线程正在运行606
线程正在运行607
线程正在运行608
线程正在运行609
线程正在运行610
线程正在运行611
线程正在运行612
线程正在运行613
线程正在运行614
线程正在运行615
main810
线程正在运行616
线程正在运行617
线程正在运行618
线程正在运行619
线程正在运行620
线程正在运行621
线程正在运行622
线程正在运行623
线程正在运行624
线程正在运行625
线程正在运行626
线程正在运行627
线程正在运行628
线程正在运行629
线程正在运行630
线程正在运行631
线程正在运行632
线程正在运行633
main811
main812
main813
main814
main815
main816
main817
main818
main819
main820
main821
main822
main823
main824
main825
main826
main827
main828
main829
main830
main831
main832
main833
main834
main835
main836
main837
main838
main839
main840
main841
main842
main843
main844
main845
main846
main847
main848
main849
main850
main851
main852
main853
main854
main855
main856
main857
main858
main859
main860
main861
main862
main863
main864
线程正在运行634
线程正在运行635
线程正在运行636
线程正在运行637
线程正在运行638
线程正在运行639
线程正在运行640
线程正在运行641
线程正在运行642
线程正在运行643
线程正在运行644
线程正在运行645
线程正在运行646
线程正在运行647
线程正在运行648
线程正在运行649
线程正在运行650
线程正在运行651
main865
main866
main867
main868
main869
main870
main871
main872
main873
main874
线程正在运行652
线程正在运行653
线程正在运行654
线程正在运行655
线程正在运行656
线程正在运行657
线程正在运行658
main875
main876
main877
main878
main879
main880
main881
main882
线程正在运行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
main883
main884
main885
main886
main887
main888
main889
main890
main891
main892
main893
main894
main895
main896
main897
main898
main899
main900
线程正在运行687
线程该停止了
main901
main902
main903
main904
main905
main906
main907
main908
main909
main910
main911
main912
main913
main914
main915
main916
main917
main918
main919
main920
main921
main922
main923
main924
main925
main926
main927
main928
main929
main930
main931
main932
main933
main934
main935
main936
main937
main938
main939
main940
main941
main942
main943
main944
main945
main946
main947
main948
main949
main950
main951
main952
main953
main954
main955
main956
main957
main958
main959
main960
main961
main962
main963
main964
main965
main966
main967
main968
main969
main970
main971
main972
main973
main974
main975
main976
main977
main978
main979
main980
main981
main982
main983
main984
main985
main986
main987
main988
main989
main990
main991
main992
main993
main994
main995
main996
main997
main998
main999

Process finished with exit code 0

线程休眠 (Sleep) : 

  • sleep(时间)指定当前线程阻塞的毫秒数
  • sleep存在异常InterruptedException
  • sleep时间达到后线程进入就绪状态
  • sleep可以模拟网络延时, 倒计时等
  • 每一个对象都有一个锁, sleep不会释放锁

使用线程休眠模拟倒计时

//模拟倒计时
public class TestSleep2{

    //倒计时10s
    public static void tenDown() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(1000);
            System.out.println(10-i);
        }
    }

    public static void main(String[] args) {
        try {
            tenDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 使用线程休眠时刻获取系统时间

public class TestSleep2{
    public static void main(String[] args) {
        //打印当前系统时间
        Date startTime = new Date(System.currentTimeMillis());//获取系统时间
        while (true){
            try {
                Thread.sleep(1000);//每一秒钟更新一次
                //输出时间
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                startTime = new Date(System.currentTimeMillis());//更新当前时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程礼让 (Yield) : 

  • 线程礼让,让当前正在执行的线程暂停, 但不阻塞
  • 将线程从运行状态转为就绪状态
  • 让cpu重新调度, 礼让不一定成功!看cpu心情
//测试礼让线程
//礼让不一定成功, 看cpu心情
public class TestYield {
    public static void main(String[] args) {
        MyYield myYield = new MyYield();
        new Thread(myYield,"a").start();
        new Thread(myYield,"b").start();
    }
}
class MyYield implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始执行");
        Thread.yield();//礼让
        System.out.println(Thread.currentThread().getName() + "线程停止执行");
    }
}

b线程开始执行
a线程开始执行
b线程停止执行
a线程停止执行

线程强制执行 (Join):

  • Join合并线程执行完成后, 再执行其他线程, 其他线程阻塞
  • 可以想象成插队
// 测试Join方法 : 想象为插队
public class TestJoin implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i<100; i++){
            System.out.println("线程vip来了"+i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 启动线程
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();

        //主线程
        for (int i = 0; i < 100; i++) {
            if (i == 50){
                thread.join();// 插队
            }
            System.out.println("main" + i);
        }
    }
}
结果 : 
main0
main1
main2
main3
main4
main5
main6
main7
main8
main9
main10
main11
main12
main13
main14
main15
main16
main17
main18
main19
main20
main21
main22
main23
main24
main25
main26
main27
main28
main29
main30
main31
main32
main33
main34
main35
main36
main37
main38
main39
main40
main41
main42
main43
main44
main45
main46
main47
main48
main49
线程vip来了0
线程vip来了1
线程vip来了2
线程vip来了3
线程vip来了4
线程vip来了5
线程vip来了6
线程vip来了7
线程vip来了8
线程vip来了9
线程vip来了10
线程vip来了11
线程vip来了12
线程vip来了13
线程vip来了14
线程vip来了15
线程vip来了16
线程vip来了17
线程vip来了18
线程vip来了19
线程vip来了20
线程vip来了21
线程vip来了22
线程vip来了23
线程vip来了24
线程vip来了25
线程vip来了26
线程vip来了27
线程vip来了28
线程vip来了29
线程vip来了30
线程vip来了31
线程vip来了32
线程vip来了33
线程vip来了34
线程vip来了35
线程vip来了36
线程vip来了37
线程vip来了38
线程vip来了39
线程vip来了40
线程vip来了41
线程vip来了42
线程vip来了43
线程vip来了44
线程vip来了45
线程vip来了46
线程vip来了47
线程vip来了48
线程vip来了49
线程vip来了50
线程vip来了51
线程vip来了52
线程vip来了53
线程vip来了54
线程vip来了55
线程vip来了56
线程vip来了57
线程vip来了58
线程vip来了59
线程vip来了60
线程vip来了61
线程vip来了62
线程vip来了63
线程vip来了64
线程vip来了65
线程vip来了66
线程vip来了67
线程vip来了68
线程vip来了69
线程vip来了70
线程vip来了71
线程vip来了72
线程vip来了73
线程vip来了74
线程vip来了75
线程vip来了76
线程vip来了77
线程vip来了78
线程vip来了79
线程vip来了80
线程vip来了81
线程vip来了82
线程vip来了83
线程vip来了84
线程vip来了85
线程vip来了86
线程vip来了87
线程vip来了88
线程vip来了89
线程vip来了90
线程vip来了91
线程vip来了92
线程vip来了93
线程vip来了94
线程vip来了95
线程vip来了96
线程vip来了97
线程vip来了98
线程vip来了99
main50
main51
main52
main53
main54
main55
main56
main57
main58
main59
main60
main61
main62
main63
main64
main65
main66
main67
main68
main69
main70
main71
main72
main73
main74
main75
main76
main77
main78
main79
main80
main81
main82
main83
main84
main85
main86
main87
main88
main89
main90
main91
main92
main93
main94
main95
main96
main97
main98
main99

线程状态观测 (State) : 

线程状态. 线程可以处于以下状态之一 :

  • new : 尚未启动的线程处于此状态
  • runnable : 在Java虚拟机中执行的线程处于此状态
  • blocked : 被阻塞等待监视器锁定的线程处于此状态
  • waiting : 正在等待另一个线程执行特定动作的线程处于此状态
  • timed_waiting : 长在等待另一个线程指定动作达到指定等待时间的线程处于此状态
  • terminated : 已退出线程处于此状态
  • 死亡之后的线程不能再次启动

一个线程可以在给定时间点处于一个状态, 这些状态是不反应任何操作系统线程状态的虚拟机状态

public class TestState {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("----------------");
        });
        //观察状态
        Thread.State state = thread.getState();
        System.out.println(state);//NEW
        //观察启动后
        thread.start();//启动线程
        state = thread.getState();
        System.out.println(state);//Run

        while (state != Thread.State.TERMINATED){// 只要线程不终止, 就一直输出状态
            Thread.sleep(100);
            state = thread.getState();// 更新线程状态
            System.out.println(state);// 输出状态
        }
    }
}
结果 : 
NEW
RUNNABLE
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TERMINATED

线程优先级 (Priority) :

  • Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程, 线程调度器按照优先级决定应该调度哪个线程来执行
  • 线程优先级用数字表示, 范围1~10
    • Thread.MIN_PRIORITY = 1;
    • Thread.MAX_PRIORITY = 10;
    • Thread.NORM_PRIORITY = 5;
  • 使用以下方法来改变或获取优先级
    • getPriority().setPriority(int xxx)
// 测试线程的优先级
public class TestPriority{
    public static void main(String[] args) {
        //主线程默认优先级
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
        MyPriority myPriority = new MyPriority();
        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);
        Thread t3 = new Thread(myPriority);
        Thread t4 = new Thread(myPriority);
        t1.start();
        t2.setPriority(1);
        t2.start();
        t3.setPriority(4);
        t3.start();
        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();
    }
}
class MyPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
    }
}
结果:
main-->5
Thread-3-->10
Thread-0-->5
Thread-2-->4
Thread-1-->1

总结 :

  • 优先级的设定建议在start()调度前
  • 优先级低只是意味着获得调度的概率低, 并不是优先级低就不会被调用了, 这都是看cpu的调度

守护(daemon)线程

  • 线程分为用户线程守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 如,后台记录操作日志, 监控内存, 垃圾回收等待..
//测试守护线程
//上帝守护你
public class TestDaemon {
    public static void main(String[] args) {
        God god = new God();
        You you = new You();

        Thread thread = new Thread(god);
        thread.setDaemon(true);//默认是false表示用户线程, 正常的线程都是用户线程
        thread.start();//守护线程启动

        new Thread(you).start();//用户线程启动
    }
}
//上帝
class God implements Runnable{

    @Override
    public void run() {
        while (true){
            System.out.println("上帝保佑你");
        }
    }
}
//你
class You implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("开心的活着");
        }
        System.out.println("=====goodbye! world!=====");
    }
}

结果:
按理说守护线程会一直运行, 但是他跟随主线程执行结束稍后结束.

线程同步 : 

  • 并发 : 同一个对象被多个线程同时操作
  • 由于同一进程的多个线程共享同一块存储空间, 在带来方便的同时, 也带来了访问冲突问题, 为了保证数据在方法中被访问时的正确性, 在访问时加入 锁机制synchronized , 当一个线程获得对象的排它锁, 独占资源, 其他线程必须等待, 使用后释放锁即可. 存在以下问题:
    • 一个线程持有锁会导致其他所有需要此锁的线程挂起;
    • 在多线程竞争下, 加锁, 释放锁会导致比较多的上下文切换和调度延时, 引起性能问题
    • 如果一个优先级高的线程等待一个优先级低的线程释放锁 会导致优先级倒置, 引起性能问题.
// 不安全的买票
// 线程不安全
public class UnsafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket station = new BuyTicket();

        new Thread(station,"我").start();
        new Thread(station,"大家").start();
        new Thread(station, "黄牛").start();
    }
}

class BuyTicket implements Runnable{
    //票
    private int ticketNums = 10;
    boolean flag = true;//外部停止方式
    @Override
    public void run() {
        //买票
        while (flag){
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    private void buy() throws InterruptedException {
        //判断是否有票
        if (ticketNums<=0){
            flag = false;
            return;
        }
        //模拟延时
        Thread.sleep(100);
        //买票
        System.out.println(Thread.currentThread().getName() + "拿到" +ticketNums--);
    }
}

结果:

大家拿到10
黄牛拿到9
我拿到10
黄牛拿到8
我拿到8
大家拿到8
黄牛拿到7
我拿到6
大家拿到6
黄牛拿到5
大家拿到3
我拿到4
大家拿到1
黄牛拿到2
我拿到0 

// 不安全的取钱
// 两个人去银行取钱, 账号
public class UnsafeBank {
    public static void main(String[] args) {
        // 账户
        Account account = new Account(100, "结婚基金");
        Drawing you = new Drawing(account, 50, "你");
        Drawing girlFriend = new Drawing(account, 100, "妻子");

        you.start();
        girlFriend.start();
    }
}
//账户
class Account{
    int money;
    String name;

    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}
//银行, 模拟取款
class Drawing extends Thread{
    Account account;//账户
    // 取了多少钱
    int drawingMoney;
    //现在手里有多少钱
    int nowMoney;
    public Drawing(Account account, int drawingMoney, String name){
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }

    @Override
    public void run() {
        //判断有没有钱
        if (account.money-drawingMoney<0){
            System.out.println(Thread.currentThread().getName()+"钱不够, 取不了");
            return;
        }
        //线程等待, 可以放大问题的发生性
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //卡内余额
        account.money = account.money-drawingMoney;
        nowMoney = nowMoney + drawingMoney;
        System.out.println(account.name + "余额为" + account.money);
        //Thread.currentThread().getName() = this,getName : 因为继承了Thread方法
        System.out.println(this.getName() + "手里的钱" + nowMoney);
    }
}

结果 : 

结婚基金余额为-50
你手里的钱50
结婚基金余额为-50
妻子手里的钱100

//线程不安全的集合
public class UnsafeList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
               list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

结果:

9998

同步方法 :

  • 由于我们可以通过private关键字来保证数据对象只能被方法访问, 所以我们只需要针对方法提出一套机制, 这套机制就是synchronized关键字, 它包括两种用法: synchronized方法和synchronized块.
  • 同步方法: public synchronized void method(int args){}
  • synchronized方法控制对"对象"的访问, 每个对象对应一把锁, 每个synchronized放大都必须获得调用该方法的对象的锁才能执行, 否则线程会阻塞, 方法一旦执行, 就独占该锁, 直到该方法返回才释放锁, 后面被阻塞的线程才能获得这个锁, 继续执行
  • 缺陷:若将一个大的方法申明为synchronized将会影响效率
//synchronized 同步方法
    private synchronized void buy() throws InterruptedException {
        //判断是否有票
        if (ticketNums<=0){
            flag = false;
            return;
        }
        //模拟延时
        Thread.sleep(100);
        //买票
        System.out.println(Thread.currentThread().getName() + "拿到" +ticketNums--);
    }

结果 : 

我拿到10
我拿到9
黄牛拿到8
黄牛拿到7
黄牛拿到6
黄牛拿到5
黄牛拿到4
黄牛拿到3
大家拿到2
大家拿到1

  • 同步块 : synchronized(Obj){}
  • Obj 称之为 同步监视器
    • Obj可以说任何对象, 但是推荐使用共享资源作为同步监视器
    • 同步方法中无需指定同步监视器, 因为同步方法的同步监视器就是this, 就是这个对象本身, 或者class
  • 同步监视器执行过程
    • 第一个线程访问, 锁定同步监视器, 执行其中代码
    • 第二个线程访问, 发现同步监视器被锁定, 无法访问
    • 第一个线程访问完毕, 解锁同步监视器
    • 第二个线程访问, 发现同步监视器没有锁, 然后锁定并访问
@Override
    public void run() {
        synchronized (account){
            //判断有没有钱
            if (account.money-drawingMoney<0){
                System.out.println(Thread.currentThread().getName()+"钱不够, 取不了");
                return;
            }
            //线程等待, 可以放大问题的发生性
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //卡内余额
            account.money = account.money-drawingMoney;
            nowMoney = nowMoney + drawingMoney;
            System.out.println(account.name + "余额为" + account.money);
            //Thread.currentThread().getName() = this,getName : 因为继承了Thread方法
            System.out.println(this.getName() + "手里的钱" + nowMoney);
        }
    }

结果 : 

结婚基金余额为50
你手里的钱50
妻子钱不够, 取不了

死锁 : 

产生死锁的四个必要条件:

  1. 互斥条件:一个资源每次只能被一个进程使用
  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
  3. 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

上面列出了死锁的四个必要条件,我们只要想办法破掉其中的任意一个或多个条件就可以避免发生死锁

//死锁:多个线程互相抱着对方需要的资源,然后形成僵持
public class DeadLock {
    public static void main(String[] args) {
        Makeup g1 = new Makeup(0,"灰姑娘");
        Makeup g2 = new Makeup(1,"白雪公主");
        g1.start();
        g2.start();
    }
}
//口红
class Lipstick{}
//镜子
class Mirror{}
//化妆
class Makeup extends Thread{
    //需要的资源只有一份, 用static保证
    static Lipstick lipstick = new Lipstick();
    static Mirror mirror = new Mirror();
    int choice;//选择
    String girlName;//用化妆品的人
    Makeup(int choice, String girlName){
        this.choice = choice;
        this.girlName = girlName;
    }
    @Override
    public void run() {
        //化妆
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //化妆, 互相持有对方的锁, 需要拿到对方的资源
    private void makeup() throws InterruptedException {
        if (choice==0){
            synchronized (lipstick){//获得口红锁
                System.out.println(this.girlName+"获得口红的锁");
                Thread.sleep(1000);
//                synchronized (mirror){//一秒钟后想获得镜子
//                    System.out.println(this.girlName +"获得镜子的锁");
//                }
            }
            synchronized (mirror){//一秒钟后想获得镜子
                System.out.println(this.girlName +"获得镜子的锁");
            }
        }else {
            synchronized (mirror){//获得镜子
                System.out.println(this.girlName+"获得镜子的锁");
                Thread.sleep(2000);
//                synchronized (lipstick){//一秒钟后想获得口红
//                    System.out.println(this.girlName +"获得口红的锁");
//                }
            }
            synchronized (lipstick){//一秒钟后想获得口红
                System.out.println(this.girlName +"获得口红的锁");
            }
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值