栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java

线程常见的构造方法

一. 多线程

1.线程常见的构造方法

1.1具体使用:1.2 线程分组使用 2. 线程常用属性3. 守护线程4.守护线程 VS 用户线程 二. 线程的常用方法

1. 线程等待 join——李四接班2. 线程的终止

2.1 使用自定义标识符终止线程2.2 使用 interrupt() 终止线程2.3 isinterrupted和interrupted 的区别: 3. yield 让出执行权4.获取当前线程5.问题:在主线程中创建两个子线程,每个子线程中产生一个随机数,最终等待子线程执行完成之后,在主线程累计两个子线程的结果。

一. 多线程 1.线程常见的构造方法
方法说明
Thread()创建线程对象
Thread(Runnable target)使用Runnable对象创建线程对象
Thread (String name)创建线程对象并命名
Thread (Runnable target ,String name)使用Runnable对象创建线程对象并命名
Thread(ThreadGroup group,Runnable target)线程可以被用来分组管理,分好的组即为线程组
1.1具体使用:
public class ThreadDemo10 {
    public static void main(String[] args) {

        //创建线程并设置线程名称
        Thread t = new Thread("线程1") {
            @Override
            public void run() {
                //休眠线程
                try {
                    Thread.sleep(60*60*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        //启动线程
        t.start();
    }
}

public class ThreadDemo11 {
    public static void main(String[] args) {

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(60*60*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"Runnable-Thread");

        thread.start();
    }
}

public class ThreadDemo10 {
    public static void main(String[] args) {

        //创建线程并设置线程名称
        Thread t = new Thread("线程1") {
            @Override
            public void run() {
                //休眠线程
                try {
                    Thread.sleep(60*60*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        //启动线程
        t.start();
    }
}

1.2 线程分组使用
import java.security.acl.Group;
import java.util.Random;

public class ThreadDemo12 {
    public static void main(String[] args) {
        //创建一个线程分组 (女子100米比赛)
        ThreadGroup group = new ThreadGroup("thread-group");

        //2.定义一个公共的任务(线程的任务)
        Runnable runTask = new Runnable() {
            @Override
            public void run() {//具体业务
                //生成一个1到3秒的随机数
                int num = (1 + new Random().nextInt(3));
                try {
                    //跑了n秒到达终点
                    Thread.sleep(num*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("选手到达终点:" + num + "s");
            }
        }78

        //3.线程(运动员)
        Thread t1 = new Thread(group,runTask);//选手1,2,3
        Thread t2 = new Thread(group,runTask);
        Thread t3 = new Thread(group,runTask);

        //开始
        t1.start();
        t2.start();
        t3.start();

        //所有人全部到达终点之后宣布成绩
        while (group.activeCount() > 0) {
        }
            System.out.println("宣布比赛成绩");
    }
}

2. 线程常用属性
属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否守护(后台)进程isDaemon()
是否存活isAlive()
是否被中断isInyerrupted()

(1). ID是线程的唯一标识,不同线程不会重复。
(2). 名称是各种调试工具用到
(3). 状态表示线程当前所处的一个情况
(4). 优先级高的线程理论上来说更容易被调度到
(5). 关于守护线程(后台线程),需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
(6).是否存活,即为run方法是否运行结束了
(7)
优先级:

ublic class ThreadDemoByPriority2 {
    private final static int MAXCOUNT = 1000;
    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                //得到当前线程
                Thread t = Thread.currentThread();
                int priority = t.getPriority();//得到线程优先级
                for (int i = 0; i < 1000 ; i++) {
                    System.out.println(t.getName() + " --优先级" + priority);

                }
            }
        },"线程1");
        t1.setPriority(Thread.MAX_PRIORITY);

        Thread t2 =new Thread(new Runnable() {
            @Override
            public void run() {
                Thread t = Thread.currentThread();
                int priority = t.getPriority();//得到线程优先级
                for (int i = 0; i < 1000 ; i++) {
                    System.out.println(t.getName() + " --优先级" + priority);
                }
                }
        },"线程2");

        t2.setPriority(Thread.MIN_PRIORITY);


        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                Thread t = Thread.currentThread();
                int priority = t.getPriority();//得到线程优先级
                for (int i = 0; i < 1000 ; i++) {
                    System.out.println(t.getName() + " --优先级" + priority);
                }

            }
        },"线程3");
        t3.setPriority(Thread.NORM_PRIORITY);

        //同时启动线程
        t2.start();
        t1.start();
        t3.start();

    }
}

结论:优先级高的大概率先执行

isAlive

public class ThreadDemoByAlive {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            Thread thread = Thread.currentThread();
            System.out.println("线程是否存活2: " + thread.isAlive());
        });
        System.out.println("线程是否存活1 " + t.isAlive());
        t.start();
        System.out.println("线程是否存活3 " + t.isAlive());
        Thread.sleep(1000);
        System.out.println("线程是否存活4 " + t.isAlive());
    }
}

3. 守护线程
public class ThreadDemoByDameon {
    public static void main(String[] args) throws InterruptedException {
        //得到当前的线程
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName() + "--是否是守护线程 " + thread.isDaemon());

        Thread t1 = new Thread(()->{
            //得到当前线程
            Thread cThread = Thread.currentThread();
            System.out.println(cThread.getName() + "--是否为守护线程 " + cThread.isDaemon());


        Thread tt1 = new Thread(()->{
            Thread cThread2 = Thread.currentThread();
            System.out.println(cThread2.getName() + "--是否为守护线程" +cThread2.isDaemon());
        },"子线程的子线程1");
        tt1.start();

        },"子线程1");



        //手动指定线程为守护线程
        t1.setDaemon(true);


        t1.start();//启动线程

        Thread.sleep(1000);
    }
}

4.守护线程 VS 用户线程


结论:

    JVM 会等待所有的用户线程执行完成后,再退出,但JVM 不会等待守护线程执行完再退出。守护线程是为用户线程服务的,没有了用户线程之后,守护线程也没有存在的必要了。
    区别:
    用户线程在Java程序中比较重要,JVM一定要等所有的用户线程执行完后才能自然结束,而守护线程就不一样了,守护线程是为用户线程服务的,当所有的用户线程执行完后,不管守护线程是否执行,JVM都会退出执行。
二. 线程的常用方法 1. 线程等待 join——李四接班

有时,我们需要等待一个线程执行完它的工作后,才能进行自己的下一步工作。

方法说明
public void join()等待线程结束
public void join(long mills)等待线程结束,最多等待 mills 毫秒
public void join(long mills,int nanos)同理,但是可以更高精度
public class ThreadByJoin {
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(()->{
            //1.张三开始上班
            System.out.println("1.张三开始上班");
            //2.张三正在上班
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //3.张三下班
            System.out.println("3. 张三下班");
        });
        //启动程序
        t1.start();

        t1.join();

        Thread t2 = new Thread(()->{
            //1.李四开始上班
            System.out.println("1.李四开始上班");
            //2.李四正在上班
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //3.李四下班
            System.out.println("3.李四下班");
        });
        t2.start();
    }
}


优点:

    写法优雅运行时所用的资源更少
2. 线程的终止 2.1 使用自定义标识符终止线程
public class ThreadInterrupet {

    //1.声明一个自定义标识符
    private static boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            while (!flag){
                System.out.println("正在转账....");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("啊? 差点误了大事!");
        });
        thread.start();

        Thread.sleep(3000);
        //终止线程
        System.out.println("有内鬼,终止交易");
        flag = true;
    }
}

2.2 使用 interrupt() 终止线程
public class ThreadInterrupt2 {
    public static void main(String[] args) throws InterruptedException {

        Thread thread = new Thread(()->{
            while (!Thread.interrupted()){
                System.out.println("正在转账...");
            }
            System.out.println("险些误了大事");
        });

        thread.start();

        Thread.sleep(100);
        //终止线程
        thread.interrupt();
        System.out.println("有内鬼,终止交易");
    }
}


interrupt() 需要配合Thread.currentThread().isInterrupted() 或 Thread.interrupted() 一块使用,从而实现线程的终止。

2.3 isinterrupted和interrupted 的区别:
    interrupted 属于静态方法,所有程序都可以直接调用的全局方法;而isinterrupted 属于某个实例的方法。interrupted 在使用完之后会重置终端标识符,而isinterrupted 不会中断标识符。
3. yield 让出执行权

yield:让出CPU的执行权

public class ThreadYield {
    public static void main(String[] args) {
        Thread t1 = new Thread(()->{
            Thread cThread = Thread.currentThread();
            for (int i = 0; i < 100; i++) {
                //让出CPU执行权
                Thread.yield();
                System.out.println("执行了线程 " + cThread.getName());
            }
        },"张三");
        t1.start();

        new Thread(()->{
            Thread cThread = Thread.currentThread();
            for (int i = 0; i < 100; i++) {
                System.out.println("执行线程:" + cThread.getName());

            }
        },"李四").start();

    }
}


yield 方法会让CPU的执行权,让线程调度器重新调度线程,但是还有一定的记录再一次调用到出让CPU的线程上的,这一次它就会执行线程的方法了,因为yield已经被执行过。

4.获取当前线程
方法说明
public static Thread currentHread();返回当前线程对象引用

5.问题:在主线程中创建两个子线程,每个子线程中产生一个随机数,最终等待子线程执行完成之后,在主线程累计两个子线程的结果。
import java.util.Random;

public class ThreadDemo14 {
    static int num1 = 0;
    static int num2 = 0;
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(()->{
            num1 = new Random().nextInt(10);
        });
        t1.start();

        Thread t2 = new Thread(()->{
            num2 = new Random().nextInt(10);

        });
        t2.start();

        t1.join();
        t2.join();
        System.out.println("最终的结果: " + (num1 + num2));
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/777260.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号