◆
如何创建线程
◆
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();
}
}
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();
}
}
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中的多线程也就基本上掌握了。
◆
线程的基本状态
◆
◆
线程的基本操作
◆
sleep:使当前线程休眠指定毫秒
yield:使当前线程让出CPU,从运行状态转到可运行状态。注意仅仅是让出,让出之后也会加入到抢占资源的队伍中。
join:把指定的线程加入到当前线程,比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B
线程停止:
Thread本身提供了一个stop方法,但是这个不推荐使用。因为使用stop的时候会暴力终止线程,从而造成数据不一致。
优雅的停止线程的代码举例如下:
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来控制线程的停止。
线程中断:
线程中断的相关方法分别是这三个
public void interrupt() ; //中断线程
public boolean isInterrupted(); //判断线程是否被中断
public static boolean interrupted(); //判断线程是否被中断,并清除当前中断状态
线程中断的代码举例如下:
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()时才会进入阻塞状态继而等待获取锁。
请看下方示例代码
package cn.shiyujun.thread.hellothread;
/**
* d
*
* @author syj
* CreateTime 2019/03/19
* describe:WaitNotify测试demo
*/
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线程已经执行完毕了。
此程序的运行结果:
WaitThread wait,time=1553088237753
NotifyThread notify,time=1553088237862
NotifyThread end,time=1553088239867
WaitThread end,time=1553088239867
suspen和resume
它们两个的功能是挂起线程和继续执行,被suspen挂起的线程必须被resume唤醒才可以继续执行。乍看起来 可以实现wait和notify的功能,不过我可不推荐你使用它们,和wait之后会释放锁不同,suspen挂起之后依然会持有锁,这个可就非常危险了。
线程组
在一个系统中如果线程数量众多而又功能比较一致,就可以把这些线程放到一个线程组里。
线程组示例代码:
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;
t1.setDaemon(true);
当一个程序中只有守护线程的时候这个程序也就要结束了。
线程的优先级
Java中的线程可以有自己的优先级,优先级高的线程在进行资源抢占的时候往往会更有优势。线程饥饿现象就是由于线程的优先级低无法抢占资源而引起的。
在Java中线程的优先级可以设置的范围是1到10之间,数字越大优先级越高。Java线程创建默认的优先级是5,我们可以线程start之前通过如下方式设置线程的优先级。
t1.setPriority(1);
收藏转发好看再走呗!
点击下方“阅读原文”查看本文所有源码!!!