创建线程的两种方式:
1.继承Thread,重写run方法,使用start()使用线程
2.将Runnable作为Thread的构造参数
复制代码
public class ThreadCreate {
public static void main(String[] args) {
System.out.println("主线程ID:" + Thread.currentThread().getId());
/**
* 第一种创建线程的方式
*/
Thread firstMethod2CreateThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("子线程ID:" + Thread.currentThread().getId());
}
});
firstMethod2CreateThread.start();
/**
* 第二种创建线程的方式
*/
class SecondMethod2CreateThread extends Thread {
@Override
public void run() {
System.out.println("子线程ID:" + Thread.currentThread().getId());
}
}
SecondMethod2CreateThread secondMethod2CreateThread = new SecondMethod2CreateThread();
secondMethod2CreateThread.start();
}
}
复制代码
Thread类详解:
JAVA中多线程的核心是Thread,Thread翻译为线程,线程有以下几种状态,接下来我会按照Thread类中的方法来逐一讲解。
复制代码
1.Thread t = new Thread()仅仅只是创建了线程,并没有为线程分配任何资源
2.start()方法用来启动线程,为相应地线程分配资源,分配到资源才能参与到竞争CPU的过程中 run():当start()启动一个线程后,线程一直等待直到获得了CPU执行时间,就进入run方法体
3.sleep()让线程休眠,主动让出CPU,但是不会释放锁,休眠时间满后,不一定立即得到执行,还需要重新参与竞争排队
public class ThreadSleep {
private int i = 0;
public Object lock = new Object();
public static void main(String[] args) {
ThreadSleep mh = new ThreadSleep();
ThreadTest tt = mh.new ThreadTest();
ThreadTest tt2 = mh.new ThreadTest();
tt.start();
tt2.start();
}
class ThreadTest extends Thread {
@Override
public void run() {
//使用的锁为Object lock = new Object(); 而不是方法所在的类的内置monitor
synchronized (lock) {
i++;
System.out.println("i:" + i);
try {
System.out.println("线程i:" + Thread.currentThread().getId() + "睡眠开始");
long startTime = System.currentTimeMillis();
Thread.currentThread().sleep(1000);
long endTime = System.currentTimeMillis();
System.out.println("线程i:" + Thread.currentThread().getId() + "睡眠时间:" + (endTime - startTime));
} catch (Exception e) {
} finally {
System.out.println("线程i:" + Thread.currentThread().getId() + "睡眠结束");
}
i++;
System.out.println("i:" + i);
}
}
}
}
复制代码
输出:
i:1
线程i:9睡眠开始
线程i:9睡眠时间:1005
线程i:9睡眠结束
i:2
i:3
线程i:10睡眠开始
线程i:10睡眠时间:1004
线程i:10睡眠结束
i:4
复制代码
4.yield()使线程让出CPU去执行相同优先级的其他程序,但是不会释放锁,(内部还是sleep)执行yield()之后该线程直接进入就绪状态再次参与竞争,生产中很少使用。
5.A线程的run()中调用了B线程的join(),则A线程等待B线程执行完之后,再继续执行,实际上调用了Object类中的wait()方法,会释放锁
public class ThreadJoin {
public static void main(String[] args) throws IOException {
System.out.println("进入线程"+Thread.currentThread().getName());
ThreadJoin test = new ThreadJoin();
MyThread thread1 = test.new MyThread();
thread1.start();
try {
System.out.println("线程"+Thread.currentThread().getName()+"等待");
thread1.join();
System.out.println("线程"+Thread.currentThread().getName()+"继续执行");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class MyThread extends Thread{
@Override
public void run() {
System.out.println("进入线程"+Thread.currentThread().getName());
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println("线程"+Thread.currentThread().getName()+"执行完毕");
}
}
}
复制代码
输出:
进入线程main
线程main等待
进入线程Thread-0
线程Thread-0执行完毕
线程main继续执行
复制代码
6.interrupt()使得处于阻塞状态的线程抛出一个异常,也就是说,它可以中断并且只能中断一个处于阻塞状态的线程
public class ThreadInterrput {
public static void main(String[] args) {
ThreadInterrput mh = new ThreadInterrput();
ThreadTest tt = mh.new ThreadTest();
tt.start();
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
}
tt.interrupt();
}
class ThreadTest extends Thread {
@Override
public void run() {
try {
System.out.println("子线程睡眠开始");
Thread.currentThread().sleep(10000);
System.out.println("子线程睡眠结束");
} catch (InterruptedException e) {
System.out.println("子线程获取到中断");
}
System.out.println("run执行完毕");
}
}
}
复制代码
输出:
子线程睡眠开始
子线程获取到中断
run执行完毕
复制代码
7.开发中一般不使用interrupt()而在类中增加isStop属性来标志是否结束while循环
class MyThread extends Thread{
private volatile boolean isStop = false;
@Override
public void run() {
int i = 0;
while(!isStop){
i++;
}
}
public void setStop(boolean stop){
this.isStop = stop;
}
}
复制代码
这样一来便可在线程外通过调用setStop方法来终止while循环。