`

Hello,Thread

阅读更多

创建线程的三种方法,线程的生命周期,sleep,yield,join,wait 和notify,线程组,守护线程,线程的优先级

如何创建线程

Java 中创建线程的方法有三种:

  1. 继承 Thread 类创建线程

新建一个类继承 Thread 类,并重写 Thread 类的 run() 方法。
创建 Thread 子类的实例。
调用该子类实例的 start() 方法启动该线程。

代码举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
public class HelloThread1 {
    static class ThreadDemo extends Thread {
        @Override
        public void run() {
            System.out.println("Hello Thread");
        }
    }
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.start();
    }
}

2.实现 Runnable 接口创建线程:

创建一个类实现 Runnable 接口,并重写该接口的 run() 方法。
创建该实现类的实例。
将该实例传入 Thread(Runnable r) 构造方法中创建 Thread 实例。
调用该 Thread 线程对象的 start() 方法。

代码举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
public class HelloThread1 {
    static class ThreadDemo extends Thread {
        @Override
        public void run() {
            System.out.println("Hello Thread");
        }
    }
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.start();
    }
}
  1. 使用 Callable 和 FutureTask 创建线程:

创建一个类实现 Callable 接口,并重写 call() 方法。
创建该 Callable 接口实现类的实例。
将 Callable 的实现类实例传入 FutureTask(Callable callable) 构造方法中创建 FutureTask 实例。
将 FutureTask 实例传入 Thread(Runnable r) 构造方法中创建 Thread 实例。
调用该 Thread 线程对象的 start() 方法。
调用 FutureTask 实例对象的 get() 方法获取返回值。

代码举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class HelloThread3 {
    static class ThreadDemo implements Callable<String> {
        @Override
        public String call() {
            System.out.println("Hello Thread");
            return "Callable return value";
        }
    }
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        FutureTask<String> futureTask = new FutureTask<String>(threadDemo);
        Thread thread = new Thread(futureTask);
        thread.start();
        try {
            System.out.println(futureTask.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


线程的生命周期

关于Java中线程的生命周期,首先看一下下面这张图:

上图中基本上囊括了Java中多线程各重要知识点。掌握了上图中的各知识点,Java中的多线程也就基本上掌握了。


线程的基本状态

新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

就绪状态(Runnable):当调用方法t.start()时,线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;同样还有几种情况会进行就绪状态,请参见上图。

运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:请参见上图。

死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。


线程的基本操作

sleep:使当前线程休眠指定毫秒

yield:使当前线程让出CPU,从运行状态转到可运行状态。注意仅仅是让出,让出之后也会加入到抢占资源的队伍中。

join:把指定的线程加入到当前线程,比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B

线程停止:
Thread本身提供了一个stop方法,但是这个不推荐使用。因为使用stop的时候会暴力终止线程,从而造成数据不一致。
优雅的停止线程的代码举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class StopThread {
    static class ThreadDemo extends Thread {
        volatile boolean stopMe = false;
        public void stopMe(){
            this.stopMe=true;
        }
        @Override
        public void run() {
            while (true) {
                if (stopMe) {
                    System.out.println("程序结束");
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.start();
        threadDemo.stopMe();
    }
}

以一个volatile修饰的变量stopMe来控制线程的停止。

线程中断:

线程中断的相关方法分别是这三个

1
2
3
public void interrupt() ; //中断线程
public boolean isInterrupted(); //判断线程是否被中断
public static boolean interrupted(); //判断线程是否被中断,并清除当前中断状态

线程中断的代码举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class InterruptThread {
    static class ThreadDemo extends Thread {
        @Override
        public void run() {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("程序结束");
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.start();
        threadDemo.interrupt();
    }
}

wait 和notify
这两个方法是JDK为了支持多线程之间的协作而提供的。
当在线程A中调用了obj.wait()方法时,线程A会停止执行进入等待状态。直到其他线程调用obj.notify()时才会进入阻塞状态继而等待获取锁。
请看下方示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class WaitNotifyThread {
    public static Object obj = new Object();

    static class WaitThreadDemo extends Thread {
        @Override
        public void run() {
            synchronized (obj) {
                try {
                    System.out.println("WaitThread wait,time=" + System.currentTimeMillis());
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("WaitThread end,time=" + System.currentTimeMillis());
            }
        }
    }

    static class NotifyThreadDemo extends Thread {
        @Override
        public void run() {
            synchronized (obj) {
                System.out.println("NotifyThread notify,time=" + System.currentTimeMillis());
                obj.notify();
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("NotifyThread end,time=" + System.currentTimeMillis());
            }
        }
    }

    public static void main(String[] args) {
        WaitThreadDemo waitThreadDemo = new WaitThreadDemo();
        NotifyThreadDemo notifyThreadDemo = new NotifyThreadDemo();
        waitThreadDemo.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        notifyThreadDemo.start();
    }
}

在上方的代码中,Wait线程会首先获取到obj的锁,当它执行wait方法时就会释放obj的锁并进入等待状态。这个时候Notify线程可以获取到obj的锁,并且唤醒Wait线程,但是因为此时Notify线程是睡眠了2秒钟之后才释放的obj的锁,所以Wait线程获取锁的时候Notify线程已经执行完毕了。
此程序的运行结果:

1
2
3
4
WaitThread wait,time=1553088237753
NotifyThread notify,time=1553088237862
NotifyThread end,time=1553088239867
WaitThread end,time=1553088239867

suspen和resume
它们两个的功能是挂起线程和继续执行,被suspen挂起的线程必须被resume唤醒才可以继续执行。乍看起来 可以实现wait和notify的功能,不过我可不推荐你使用它们,和wait之后会释放锁不同,suspen挂起之后依然会持有锁,这个可就非常危险了。

线程组
在一个系统中如果线程数量众多而又功能比较一致,就可以把这些线程放到一个线程组里。
线程组示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ThreadGroupDemo {
    static class ThreadDemo extends Thread {
        @Override
        public void run() {
            while (true){
                System.out.println("I am "+Thread.currentThread().getThreadGroup().getName()+"-"+Thread.currentThread().getName());
                try {
                    sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        ThreadGroup threadGroup=new ThreadGroup("groupDemo");
        Thread t1=new Thread(threadGroup,new ThreadDemo(),"t1");
        Thread t2=new Thread(threadGroup,new ThreadDemo(),"t2");
        t1.start();
        t2.start();
    }
}

守护线程
在线程的世界里,由我们自己创建的线程叫用户线程。而一些系统创建的线程,如垃圾回收线程等被称之为守护线程,如果想要把一个用户线程设置为守护线程可以在线程的调用线程的start方法前设置线程的daemon属性为true;

1
t1.setDaemon(true);

当一个程序中只有守护线程的时候这个程序也就要结束了。

线程的优先级

Java中的线程可以有自己的优先级,优先级高的线程在进行资源抢占的时候往往会更有优势。线程饥饿现象就是由于线程的优先级低无法抢占资源而引起的。
在Java中线程的优先级可以设置的范围是1到10之间,数字越大优先级越高。Java线程创建默认的优先级是5,我们可以线程start之前通过如下方式设置线程的优先级。

1
t1.setPriority(1);

本文所有源码https://github.com/shiyujun




 
 


  • 大小: 171.6 KB
0
0
分享到:
评论

相关推荐

    多线程显示的三种不同方式显示hello world

    Thread thread1 = new Thread(hello1::printHello); Thread thread2 = new Thread(hello2::printHello); thread1.start(); thread2.start(); } } ``` 在这个例子中,`synchronized`关键字确保了`print...

    Windows API 多线程编程

    printf("Hello Thread\n"); return 0; } int main() { HANDLE hThread = CreateThread( NULL, // 使用默认的安全属性 0, // 使用系统默认的栈大小 helloFunc, // 指向线程函数的指针 NULL, // 没有传递...

    pthread的helloworld

    ### pthread的helloworld #### 知识点概览 1. **pthread库简介** 2. **线程创建函数`pthread_create()`详解** 3. **线程ID获取与使用:`pthread_self()`** 4. **线程函数参数传递** 5. **错误处理机制** 6. **代码...

    tcl thread 在linux 下的安装包

    puts "Hello, World! I'm running in a new thread." }] # 等待新线程执行完毕 thread::join $threadId puts "Main thread finished." ``` 这段代码会创建一个新的线程,并在其中打印一条消息,然后主线程等待新...

    RT-thread添加模块方法.doc

    在本文中,我们将深入探讨如何在RT-thread操作系统中添加新的模块。RT-thread是一个开源、可扩展的实时操作系统,广泛应用于物联网(IoT)设备和嵌入式系统中。当需要在RT-thread项目中引入新的功能或者自定义组件时,...

    java版HelloWorld攻略

    3. **运行时错误**:例如“`Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld`”。此类错误通常是由于JVM找不到类文件导致的,可以通过设置正确的CLASSPATH来解决。 4. **NoSuchMethodError:...

    Hello.Android.3rd.Edition 源代码

    11. **异步处理**:Android中通常避免在主线程执行耗时操作,源代码可能包含`AsyncTask`、`Handler`、`Runnable`和`Thread`的使用,以及现代的`LiveData`和`ViewModel`。 12. **动画(Animation)和过渡...

    STM32F103移植rt-thread

    7. **编写“hello world”**:创建一个简单的任务,例如在串口上打印"Hello, rt-thread!",以验证rt-thread的运行。 8. **编译与烧录**:编译工程并下载到STM32F103芯片中,通过串口终端观察输出,确认rt-thread...

    rtthread-stm32f2空工程

    可以创建一个初始任务,输出“Hello, RTThread!”这样的信息,验证任务调度、中断等功能是否正常工作。 在实际移植过程中,可能会遇到各种问题,如内存分配失败、中断未响应、时钟配置错误等。这些问题需要根据错误...

    出现Exception in threadmain java.lang.NoClassDefFoundError的各种可能情况.doc

    在Java编程中,遇到“Exception in thread 'main' java.lang.NoClassDefFoundError”是一种常见的异常情况,这通常意味着JVM在运行时未能找到指定的类定义。此错误不同于ClassNotFoundException,后者发生在尝试加载...

    c++ thread_local(csdn)————程序.pdf

    在上面的代码中,我们声明了一个名为 s 的 Thread_Local 变量,并初始化为 "hello from "。这个变量的生命周期与所属的线程一样长,每个线程都有自己的副本。 Thread_Local 关键字的优点是,它可以解决多线程环境下...

    理解java的helloworld[归类].pdf

    如果尝试运行`java HelloWorld`而得到“Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld”的错误,这通常是因为类路径(classpath)未正确设置。类路径指示Java虚拟机在何处查找类文件。在...

    python 多thread编程

    Thread-1 says Hello World at time: 2023-09-14 13:22:50.252069 Thread-2 says Hello World at time: 2023-09-14 13:22:50.252576 ``` #### 三、使用`threading.Thread`创建线程 在上面的例子中,我们定义了一个...

    C++ Boost Thread 编程指南

    boost::thread thrd(hello); // 使用默认构造函数创建线程 thrd.join(); // 等待线程结束 return 0; } ``` 在这个例子中,通过`boost::thread`类创建了一个新的线程,该线程执行`hello()`函数。`thrd.join();`...

    Hello_Android_美Ed_Burnette著_张波等译(中文版)

    9. **多线程与异步处理**:掌握AsyncTask、Handler、Thread和Runnable等多线程技术,以及如何避免主线程阻塞。 10. **调试与测试**:学习如何使用Android Studio的调试工具进行问题排查,以及编写单元测试和 ...

    boost 1.61 编译好的包 win32 TDM-GCC5.1.0 static 这个才是32位的

    boost::thread thread1(&hello); boost::thread thread2(&hello); boost::thread thread3(&hello); boost::thread thread4(&hello); thread1.join(); thread2.join(); thread3.join(); thread4.join(); ...

    联盛德W601实现MQTT协议通信【RT-Thread工程,支持W60X系列单片机】.zip

    在本文中,我们将深入探讨如何使用联盛德W601单片机通过RT-Thread实时操作系统实现MQTT协议通信。联盛德W601是一款高性能、低功耗的微控制器,常用于物联网(IoT)应用。而MQTT(Message Queuing Telemetry Transport...

    activiti入门程序helloworld及所需整合jar包

    保存为 hello.bpmn20.xml 和 hello.png。 2. 部署流程:在 Java 代码中,使用 Activiti 引擎的 RepositoryService 进行部署: ```java RepositoryService repositoryService = processEngine.getRepositoryService...

Global site tag (gtag.js) - Google Analytics