多线程---创建及方法

发布于:2024-12-06 ⋅ 阅读:(19) ⋅ 点赞:(0)

*线程创建的方式:

1.继承Thread类,重写run方法。

2.实现Runnable接口,重写run方法。

实际这两个run方法都重写的是Runnable中的run方法

简化方法:

1.匿名内部类创建Thread 子类对象

Thread thread = new Thread(){
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("hello Thread...");
                }
            }
        };

模板:

Thread thread = new Thread()

run(   )

};

2.匿名内部类创建Runnable子类,实现Runnable接口,并重写run方法

Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("hello Runnable...");
                }
            }
        });

模板:

Thread thread1 = new Thread(new Runnable() {
           run()
        }
);

3.lambda表达式创建

Thread thread2 = new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("hello lambda...");
            }
        });

模板:

Thread thread2 = new Thread(() -> {
           语句
        }
);

*多线程的实现

假如有一个任务,分别让一个人单独完成,和二个人同时完成。显然是二个人较快。

多线程也是如此。

例如:

public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            while (true) {
                System.out.println("工作任务-5...");
            }
        });
        Thread thread2 = new Thread(() -> {
            while (true) {
                System.out.println("工作任务-5...");
            }
        });
        //多线程
        thread1.start();
        thread2.start();
    }

当任务较大时,多线程可以节省将近一半时间。

当任务较少时,不建议使用多线程,这会造成系统资源浪费。 

* 线程类及其常见方法

1.常见构造方法 

在后台查看线程时,如果每个线程都有自己的名字,那么出错时就会很快找到。

Thread()创建线程对象

Thread(Runnable  target)使用Runnable对象创建线程

Thread(String name)创建线程对象,并命名

Thread(Runnable  target , String name)使用Runnable对象创建线程,并命名

public class Thread_name {
    public static void main(String[] args) {
        Thread thread4 = new Thread(() ->{
            while (true) {
                System.out.println("我有名字:" + Thread.currentThread().getName());
            }
        },"Thread");
        thread4.start();
    }
}

注:  Thread.currentThread()用于线程内调用线程对象

2. Thread的几个常见属性

属性 获取方法
ID getId()
名称 getName()
状态 getState()
优先级 getPriority()
是否后台线程 isDaemon()
是否存活 isAlive()
是否被中断 isInterrupted()
• ID 是线程的唯⼀标识,不同线程不会重复
这个ID是JVM默认为Thread对象生成的编号,属于Java层面,要和PCB区分开,PCB是操作系统层面的
名称 是各种调试⼯具⽤到
状态 表⽰线程当前所处的⼀个情况
也是JAVA层面的

我们看一看有哪些状态: 

NEW:表示创建好了一个Java线程对象,安排好了任务,处于准备就绪状态。

但是还没有启动没有调用start()方法之前是不会创建PCB的,和PCB没有任何关系


RUNNABLE:正在运行+准备就绪状态,最常见的状态

有系统PCB


BLOCKED:等待锁的状态,阻塞的一种。(因为 锁竞争 引起的阻塞)


WAITING :没有等待时间,一直死等,直到被唤醒。


TIMED_WAITING:指定了等待时间的阻塞状态,过时不侯


TERMINATED:结束,完成状态,PCB已经销毁,但是JAVA线程对象还在

线程已经结束,Thread对象还存在

• 优先级 ⾼的线程理论上来说更容易被调度到
字面意思
关于 后台线程 ,需要记住⼀点:JVM会在⼀个进程的所有⾮后台线程结束后(即前台线程),才会结束运⾏。

 创建线程时默认是前台线程
前台线程可以阻止进程的退出
后台线程不阻止进程的退出

设置成后台线程之后,main方法执行完成之后整个程序就退出了,子线程也就自动结束了
如果是前台线程子线程不会受main方法的影响会一直运行下去 

是否 存活 ,即简单的理解,为 run ⽅法是否运⾏结束了
描述的是PCB的状态,可以查看run()方法是否执行完成
public static void main(String[] args) {
        Thread thread = new Thread(() -> {
                System.out.println("我的名字:" + Thread.currentThread().getName());
        });
        System.out.println(thread.getName() + "Id:" + thread.getId());
        System.out.println(thread.getName() + "状态:" + thread.getState());
        System.out.println(thread.getName() + "优先级:" + thread.getPriority());
        System.out.println(thread.getName() + "后台线程:" + thread.isDaemon());
        System.out.println(thread.getName() + "活着:" + thread.isAlive());
        System.out.println(thread.getName() + "被中断:" + thread.isInterrupted());
        thread.start();
        //执行后
        System.out.println(thread.getName() + "后台线程:" + thread.isDaemon());
        System.out.println(thread.getName() + "活着:" + thread.isAlive());
        System.out.println(thread.getName() + "被中断:" + thread.isInterrupted());
    }

3.启动一个线程start()

在没有启动线程之前,复写run()方法是发布要执行的任务,创建线程实例是把做任务的人叫了过来,到还没真正开始做任务,只有调用start()方法,这个“线程"才会去执行任务。

4.终止一个线程

1.使用interrupt ()方法,终止一个线程

    public static void main(String[] args) {
        Thread th = new Thread(() -> {
             while(true) {
                 try {
                     Thread.sleep(1000);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 System.out.println("我在执行...");
             }
        });
        th.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("快终止线程!!");
        th.interrupt();
    }

如果程序正常执行他在打印五个执行之后就会被终止但是实际运行却报了异常。

这是因为线程终止时,中止的是sleep方法

这个时候我们就需要在sleep方法中进行逻辑处理,使其达到目标,也就是终止程序

 2.自定义一个标志位用于通知线程中断

 

lambda里面如果使用局部变量
触发“变量捕获
需要把这个变量定义为全部的 

全局静态变量 

5.等待一个线程join

 有时候我们需要等待一个线程结束后才开始另一个线程,例如:准备好原材料后才能开始制作产品。这时我们就需要join()方法

方法 说明
public void join() 等待线程结束
public void join(long millis) 等待线程结束,最多等millis毫秒
public void join(long millis, int nanos) 同理,但精度更高

 6.获取当前线程的引用

方法 说明
public static Thread currentThread() 获取当前对象的引用

 使用在Thread内部,调用自身


网站公告

今日签到

点亮在社区的每一天
去签到