线程的创建方法:
1:显示继承Thread类,并重现run方法来指定线程执行的代码.
//创建子类继承自Thread,并重写run方法
class MyThread extends Thread{
public void run(){
//描述线程内部要执行那些代码,每个线程都是并发执行的(各自执行各自的代码)因此要告诉这个线程要执行的代码是啥
System.out.println("hello thread");
}
}
ps:run方法中逻辑是在新创建的线程中被执行的代码,并不是一定要定义这个类,一写run方法,线程就创建出来了.相当于把任务安排了,但是没开始干.
public class ThreadDemo1 {
public static void main(String[] args) {
Thread t = new MyThread();
t.start();
}
}
在调用start之前,系统是没有创建出线程的,这里调用start之后才是真正的在系统中创建了线程,才真正开始执行run操作.
2:创建一个类实现Runnable接口,在创建Runnable实例传给Thread实例
//创建一个Runnable接口,再创建一个Runnable实例传给Thread实例
class MyRunnable implements Runnable{
@Override
public void run() {
}
}
public class ThreadDemo2 {
public static void main(String[] args) {
//显示创建一个类,实现Runnable接口,然后把这个Runnable的实例关联到Thread实例上
Thread t = new Thread(new MyRunnable());
t.start();
}
}
3.创建Thread类,使用匿名内部类:
public class ThreadDemo3 {
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run(){
System.out.println("hello thread");
}
};
t.start();
}
}
4.使用Runnable接口,并使用匿名内部类重写run方法:
public class ThreadDemo4 {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello thread");
}
});
t.start();
}
}
5.使用lambda表达式:
public class ThreadDemo5 {
public static void main(String[] args) {
Thread t = new Thread(()->{
System.out.println("hello thread");
});
t.start();
}
}
线程中断:
线程中断:让一个线程停下来,关键是让一个线程对应的run方法执行(对于main线程来说,main方法执行完了,main线程就完了).
1.可以手动设置一个标志位,(自己创建一个变量(boolean)来控制线程是否结束执行).
public class ThreadDemo6 {
private static boolean isQuit = false;
public static void main(String[] args){
Thread t = new Thread(()->{
while (!isQuit){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//只要把isQuit改为true,这个时候循环就退出了,run也就执行完了,进而线程就结束了
isQuit = true;
System.out.println("终止t线程");
}
}
ps:这个方法也有不严谨的地方.
2.使用Thread内置的一个标志位来进行判定,可以通过T和read.interrupted()这个静态方法.
public class ThreadDemo7 {
public static void main(String[] args) {
Thread t = new Thread(()->{
while (!Thread.currentThread().isInterrupted()){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//在main线程中调用interrupt这个方法来中断这个线程.
t.interrupt();
System.out.println(t.isInterrupted());
}
}
线程等待:
多个线程之间,调度顺序是不确定的,线程之间的执行是按照调度器来安排的,这个过程是"无序,随机",这样不太好,有些时候,我们需要能控制线程之间的顺序,线程等待就是其中一种,控制线程执行顺序的手段,此处的等待,主要是控制线程结束的先后顺序
class Count{
public int count = 0;
public synchronized void add(){
count++;
}
}
public class ThreadDemo8 {
public static void main(String[] args) throws InterruptedException {
Count c = new Count();
Thread t1 = new Thread(()->{
for (int i = 0; i < 1000; i++) {
c.add();
}
});
t1.start();
//当主线程走到join时就会阻塞,等到t1线程执行完毕,才会继续执行主线程(t1线程肯定比主线程先执行结束)
t1.join();
System.out.println(c.count);
}
}
ps:当主线程执行到join时就会阻塞,进入阻塞队列,直到thread线程执行结束,主线程才会进入就绪队列,才可以被操作系统内核调度.
线程休眠:
线程休眠会由就绪队列换到阻塞队列。当指定的休眠时间结束,就可以由阻塞队列回到就绪队列。这样才可以被调度,所以休眠时间会大于等于我们指定的时间。java里使用sleep()方法,参数以毫秒位单位。
注意:上述代码里使用的sleep均为线程休眠。
获取当前线程实例:
public class ThreadDemo10 {
public static void main(String[] args) {
Thread t = Thread.currentThread();
System.out.println(t.getName());
}
}
调用方式:Thread.currentThread(),返回的是线程对象的引用,有时候可以用this代替