创建线程的三种方法,线程的生命周期,sleep,yield,join,wait 和notify,线程组,守护线程,线程的优先级
◆
如何创建线程
◆
Java 中创建线程的方法有三种:
- 继承 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 { 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 { public void run() { System.out.println("Hello Thread"); } } public static void main(String[] args) { ThreadDemo threadDemo = new ThreadDemo(); threadDemo.start(); } } |
- 使用 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; } 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 { 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 { 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 { 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
相关推荐
boost::thread thread1(&hello); boost::thread thread2(&hello); boost::thread thread3(&hello); boost::thread thread4(&hello); thread1.join(); thread2.join(); thread3.join(); thread4.join(); ...
多线程编程 简单教学 直接gcc就可以编译的文件, 希望对大家有用 - -
操作系统进程管理实验
activiti整合所需jar包及eclipse静态安装所需文件
线程流 一种将数据发送到Node.js工作线程的流传输方式。 安装 npm i thread-stream 用法 'use strict' const ThreadStream = require ( 'thread-stream' ) const { join } = ... write ( 'hello' ) // Asynchronous
可异步执行任何与定义的用户自定义方法和函数... printf("Hello %s\n", $this->arg); } } } $thread = new AsyncOperation("World"); if($thread->start()) $thread->join(); ?> 标签:pthreads
Console.WriteLine(hello world); } 2、带一个参数的线程 使用ParameterizedThreadStart,调用 System.Threading.Thread.Start(System.Object) 重载方法时将包含数据的对象传递给线程。 注意传递的参数只能是object...
DuiCreator是为DuiLib(Direct UI Library)提供的IDE。她基于QtCreator开发,提供VC2010编译器,代码编写,调试,所见即...(2)轻松构建DuiLib HelloWorld By DuiCreator(下)http://duilibcn.com/thread-45-1-1.html
输入:Hello World 输出:HelloListener:Hello World - :Thread-Name 输出:WorldListener:Hello World - :Thread-Name 春天 好处 自 spring 3 以来内置于 spring。 建立订阅者和发出事件相当容易。 可能的缺点 ...
其中hello.c和hello.h是2.3.2的源代码,gdb.c是2.4.1的源代码,test.c是动手练练的源代码。 程序代码\chapter06 文件夹中包含了第6章的示例源程序。其中pointer1.c是6.2.2的第一个源代码,pointer2.c是6.2.2的第二个...
适合有一点STM32裸机基础,继续了解物联网系统的同学,本例程为库函数版本将RT_Thread Finsh组件移植到STM32F4系列单片机,具体修改如下: 通讯参数: 使用STM32F407的串口1进行Finsh通讯,需要使用其他串口可自行更改:...
gcc demo_main.c thread_cond.c thread_mutex.c thread_pool.c -o demo_main -lpthread 运行 ➜ Nginx_-_- git:(main) ✗ ./demo_main Hello, this is 1th test.index=0 Hello, this is 2th test.index=0 Hello, ...
使用rtthread的i2c驱动框架做的小练习,供各位下载学习,不用积分,行的给我点个赞。
cap io mul_thread_download qq sem tcp tcp_dos testerr time wav ./broadcast: broad.h client.c server server.c ./cap: capture_packet capture_packet.c ./icmp: icmp.c ./io: aa ba conf filename.c ...
soa/AxisHelloWorldServer.zip //16.Axis服务端——HelloWorld实例 soa/AxisHelloWorldClient.zip //16.Axis客户端——HelloWorld实例 soa/SCAJavazip //19.SCA实例——计算器实例 soa/SCAWSServer.zip //19.SCA...
uml/statechart_thread.mdl //05.状态图——Java线程类Thread uml/activity_bug.mdl //06.活动图——Bug管理系统 uml/activity_atm.mdl //06.活动图——ATM机存取款 uml/activity_thread.mdl //06.活动图——...
uml/statechart_thread.mdl //05.状态图——Java线程类Thread uml/activity_bug.mdl //06.活动图——Bug管理系统 uml/activity_atm.mdl //06.活动图——ATM机存取款 uml/activity_thread.mdl //06.活动图——...
soa/AxisHelloWorldServer.zip //16.Axis服务端——HelloWorld实例 soa/AxisHelloWorldClient.zip //16.Axis客户端——HelloWorld实例 soa/SCAJavazip //19.SCA实例——计算器实例 soa/SCAWSServer.zip //19.SCA...
soa/AxisHelloWorldServer.zip //16.Axis服务端——HelloWorld实例 soa/AxisHelloWorldClient.zip //16.Axis客户端——HelloWorld实例 soa/SCAJavazip //19.SCA实例——计算器实例 soa/SCAWSServer.zip //19.SCA...
uml/statechart_thread.mdl //05.状态图——Java线程类Thread uml/activity_bug.mdl //06.活动图——Bug管理系统 uml/activity_atm.mdl //06.活动图——ATM机存取款 uml/activity_thread.mdl //06.活动图——...