java多线程学习随笔

常用方法学习

  • join

  当在一个线程中调用另一个线程的join()方法时,当前线程转入阻塞状态,等待另一个线程执行结束后再继续执行当前线程。

  示例:

public class ThreadJoinDemo {

    public static void main(String[] args) throws InterruptedException {
        System.out.println("Main Thread start!");
        Thread1 thread1 = new Thread1("A");
        Thread thread2 = new Thread1("B");
        thread1.start();
        thread2.start();
        //此处不添加join方法,则主线程会先结束,然后A、B线程结束
        //添加join方法后,主线程会在A、B线程结束后再结束
        thread1.join();
        thread2.join();
        System.out.println("Main Thread end!");
    }

    static class Thread1 extends Thread {

        private String name;

        public Thread1(String name) {
            super(name);
            this.name = name;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " start");
            for (int i = 0; i < 5; i ++) {
                System.out.println("子线程" + name + "run:" + i);
                try {
                    sleep((long) (Math.random() * 10));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " end");
        }
    }
}
View Code

  如果把join方法注释掉,则结果如下,主线程先结束,然后线程A、B结束:

Main Thread start!
A start
子线程Arun:0
Main Thread end!
B start
子线程Brun:0
子线程Brun:1
子线程Arun:1
子线程Arun:2
子线程Brun:2
子线程Brun:3
子线程Brun:4
子线程Arun:3
B end
子线程Arun:4
A end
View Code

  join方法放开的话,则主线程会等A、B线程结束后再结束:

Main Thread start!
A start
子线程Arun:0
B start
子线程Brun:0
子线程Arun:1
子线程Brun:1
子线程Brun:2
子线程Arun:2
子线程Brun:3
子线程Arun:3
子线程Arun:4
A end
子线程Brun:4
B end
Main Thread end!
View Code
  •  yield

  线程回到可执行状态,允许具有相同优先级的其他线程执行。但是并非一定会执行其他线程,因为该线程可能被调度器再度调起。

  与sleep()区别:sleep方法让当前线程回到停滞状态,在sleep持续时间内,该线程肯定不会执行。sleep时,会执行其他低优先级的线程;yield执行后,线程仍是可执行状态,低优先级线程仍然无法获得cpu资源。

  代码示例:

public class YieldDemo {

    static class YieldThread extends Thread {

        public YieldThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                System.out.println(this.getName() + "----" + i);
                if (i == 30) {
                    //当i=30时,该线程把资源让给其他线程执行。
                    yield();
                }
            }
        }
    }

    public static void main(String[] args) {

        YieldThread t1 = new YieldThread("a");
        YieldThread t2 = new YieldThread("b");

        t1.start();
        t2.start();
    }
}
View Code

  第一种情况,线程a未让出资源,继续执行:

"C:\Program Files\Java\jdk1.7.0_80\bin\java" "-javaagent:D:\IntelliJ IDEA 2017.1\lib\idea_rt.jar=57766:D:\IntelliJ IDEA 2017.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_80\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\rt.jar;E:\workspace-sets\workspace-demo\thread-demo\target\classes" com.xc.thread.yield.YieldDemo
a----0
a----1
a----2
a----3
a----4
a----5
a----6
a----7
a----8
a----9
a----10
a----11
a----12
a----13
a----14
a----15
a----16
a----17
a----18
a----19
a----20
a----21
a----22
a----23
a----24
a----25
a----26
a----27
a----28
a----29
a----30
a----31
a----32
a----33
a----34
a----35
a----36
a----37
a----38
a----39
a----40
a----41
a----42
a----43
a----44
a----45
a----46
a----47
a----48
a----49
b----0
b----1
b----2
b----3
b----4
b----5
b----6
b----7
b----8
b----9
b----10
b----11
b----12
b----13
b----14
b----15
b----16
b----17
b----18
b----19
b----20
b----21
b----22
b----23
b----24
b----25
b----26
b----27
b----28
b----29
b----30
b----31
b----32
b----33
b----34
b----35
b----36
b----37
b----38
b----39
b----40
b----41
b----42
b----43
b----44
b----45
b----46
b----47
b----48
b----49

Process finished with exit code 0
View Code

  第二种情况,线程a和线程b执行到第30次时,都让出了资源:

a----0
a----1
a----2
a----3
a----4
a----5
a----6
a----7
a----8
a----9
a----10
a----11
a----12
a----13
a----14
a----15
a----16
a----17
a----18
a----19
a----20
a----21
a----22
a----23
a----24
a----25
a----26
a----27
a----28
a----29
a----30
b----0
b----1
b----2
b----3
b----4
b----5
b----6
b----7
b----8
b----9
b----10
b----11
b----12
b----13
b----14
b----15
b----16
b----17
b----18
b----19
b----20
b----21
b----22
b----23
b----24
b----25
b----26
b----27
b----28
b----29
b----30
a----31
a----32
a----33
a----34
a----35
a----36
a----37
a----38
a----39
a----40
a----41
a----42
a----43
a----44
a----45
a----46
a----47
a----48
a----49
b----31
b----32
b----33
b----34
b----35
b----36
b----37
b----38
b----39
b----40
b----41
b----42
b----43
b----44
b----45
b----46
b----47
b----48
b----49
============================
over
============================

Process finished with exit code 0
View Code
  • wait和notify

  wait:线程在synchronized代码块获得对象的锁后,通过wait()方法释放对象锁,同时线程休眠,直到其他线程调用对象的notify()方法唤醒该线程。

  notify:唤醒一个正在等待该对象的线程。不过,notify并不是立即唤醒,而是在synchronized执行结束后唤醒。

  代码示例:

public class WaitNotifyDemo {

    static class PrintThread implements Runnable {

        private String name;
        private Object prev;
        private Object self;

        public PrintThread(String name, Object prev, Object self) {
            this.name = name;
            this.prev = prev;
            this.self = self;
        }

        @Override
        public void run() {

            int count = 10;
            while (count > 0) {
                //先锁住prev
                synchronized (prev) {
                    //再锁self
                    synchronized (self) {
                        System.out.println(name);
                        count--;

                        //唤醒等待self的线程
                        self.notify();
                    }
                    try {
                        //当前线程阻塞,交出prev对象的控制
                        prev.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Object a = new Object();
        Object b = new Object();
        Object c = new Object();

        PrintThread t1 = new PrintThread("A", c, a);    //线程A持有c和a的对象锁
        PrintThread t2 = new PrintThread("B", a, b);    //线程B持有a和b的对象锁
        PrintThread t3 = new PrintThread("C", b, c);    //线程C持有b和c的对象锁

        //线程A开始执行,先持有c,a的对象锁,打印完成后先释放a,唤醒了等待a锁的线程B;然后再释放了c,自身进入休眠状态。
        new Thread(t1).start();
        Thread.sleep(100);//确保线程按顺序执行
        //线程B被唤醒后,这时a,b锁都没被占用,开始执行,并持有a、b的对象锁,打印操作完成了再释放了b,唤醒了等待b锁的c;然后再释放a,进入休眠状态
        new Thread(t2).start();
        Thread.sleep(100);
        //线程C被唤醒,申请了b,c的锁,打印完成后释放了c,又唤醒了等待c锁的线程A
        new Thread(t3).start();
        Thread.sleep(100);

    }
}
View Code

  结果展示:

"C:\Program Files\Java\jdk1.7.0_80\bin\java" "-javaagent:D:\IntelliJ IDEA 2017.1\lib\idea_rt.jar=58550:D:\IntelliJ IDEA 2017.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_80\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\rt.jar;E:\workspace-sets\workspace-demo\thread-demo\target\classes" com.xc.thread.wait.WaitNotifyDemo
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
View Code

  简单说明:

  线程A最先执行,并持有了a和c的对象锁,在打印完成后,调用self.notify()实际是a.notify,这时唤醒了等待a锁的线程B。

  在线程A里面的synchronized代码块执行完成后,a对象的锁被释放,线程B此时持有了a和b的对象锁,因此可以执行打印方法。打印完成后唤醒了等待b对象的线程c。这时线程A的第二个代码块也执行结束,释放了对象c,线程A进入休眠。

  线程B唤醒线程C后释放了b对象,线程C可以执行,并持有了c和b的对象锁。再打印完释放对象c后,线程A又可以执行了。

  • Lock和Condition

  使用lock对象锁来控制多个线程对同一资源的同步互斥。使用Condition来控制多个线程之间的等待/通知。

  Condition的await()方法用于释放资源并等待唤醒,类似object.wait();

  Condition的signal()方法用于唤醒等待该资源的线程,类似object.signal();

  下面一段代码是通过Lock和Condition来实现线程间的通信,是线程可以有序地交替执行:

/**
 * 通过lock和condition实现线程间通信,使线程A打印3次后打印1次线程B
 * Created by xuec on 2019/3/7.
 */
public class LockDemo {

    private static Lock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();

    static class ThreadOne extends Thread {

        private String name;

        public ThreadOne(String name) {
            super(name);
            this.name = name;
        }

        @Override
        public void run() {
            for (int i = 1; i < 50; i++) {
                try {
                    //线程A先执行,获得对象锁,这时线程B无法执行
                    lock.lock();
                    while (ThreadToGo.value == 2) {
                        //当value为2时,线程A开始等待
                        condition.await();
                    }
                    System.out.println(i + "---" + name);
                    if (i % 3 == 0) {
                        //线程A执行3次后,值改为2,下次执行时,会这是当前线程进入等待状态
                        ThreadToGo.value = 2;
                    }
                    //每次输出结束都会唤醒等待的线程
                    condition.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    static class ThreadTwo extends Thread {

        private String name;

        public ThreadTwo(String name) {
            super(name);
            this.name = name;
        }

        @Override
        public void run() {
            for (int i = 1; i < 50; i++) {
                try {
                    lock.lock();
                    while (ThreadToGo.value == 1) {
                        condition.await();
                    }
                    System.out.println(i + "---" + name);
                    if (i % 3 != 0) {
                        ThreadToGo.value = 1;
                    }
                    condition.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    static class ThreadToGo {
        static int value = 1;
    }

    public static void main(String[] args) {
        ThreadOne t1 = new ThreadOne("A");
        ThreadTwo t2 = new ThreadTwo("B");
        t1.start();
        t2.start();
    }
}
View Code

  输出结果如下:

1---A
2---A
3---A
1---B
4---A
5---A
6---A
2---B
7---A
8---A
9---A
3---B
4---B
10---A
11---A
12---A
5---B
13---A
14---A
15---A
6---B
7---B
16---A
17---A
18---A
8---B
19---A
20---A
21---A
9---B
10---B
22---A
23---A
24---A
11---B
25---A
26---A
27---A
12---B
13---B
28---A
29---A
30---A
14---B
31---A
32---A
33---A
15---B
16---B
34---A
35---A
36---A
17---B
37---A
38---A
39---A
18---B
19---B
40---A
41---A
42---A
20---B
43---A
44---A
45---A
21---B
22---B
46---A
47---A
48---A
23---B
49---A
View Code

 

转载于:https://www.cnblogs.com/snowcity1231/p/10480177.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值