一、进程与线程
一个进程可以包含一个以上的线程,CPU 时间片切换的基本单位是线程。
二、创建线程
(一)继承 Thread 类
public class Task extends Thread{@Override //重写run方法public void run(){System.out.println("this is a thread");}public static void main(String[] args){Task task=new Task();task.start();}
}
(二)实现 Runnable 接口
public class Task implements Runnable{@Override //重写run方法public void run(){System.out.println("this is a thread");}public static void main(String[] args){Task task=new Task();Thread thread=new Thread(task); //利用Thread的构造方法创建一个线程thread.start();}
}
(三)实现 Callable 接口
public class Task implements Callable<String>{@Override //重写run方法public String call(){return "this is a thread";}public static void main(String[] args){Task task=new Task();FutureTask<String> ft=new FutureTask(task);Thread thread=new Thread(ft); //利用Thread的构造方法创建一个线程thread.start();String x=ft.get();System.out.println(x);}
}
除 Thread 之外,无论 Runnable 还是 Callable 都无法独立启动线程,都需要借助 Thread 才能实现线程启动。
三、获取当前线程
① 获取当前进程:Thread.currentThread()
② 获取当前进程的名称:Thread.currentThread().getName()
③ 设置当前进程的名称:Thread.currentThread().setName(String name)
④ 获取当前线程的级别:Thread.currentThread().getPriority()
⑤ 设置当前线程的级别:Thread.currentThread().setPriority()
四、run() 方法与 start() 方法的区别
run() 方法用于存放任务代码,但直接调用 run() 方法无法启动线程,只是调用了一个普通的 run 方法,因此可以调用无限次。start() 方法用于启动线程,只能启动一次,连续启动会报错,线程启动之后会自动调用 run 方法里面的任务代码。
五、线程休眠
Thread.sleep(int x) x 表示毫秒数
六、线程让渡执行权
Thread.yield() 表示暂停当前线程,将 CPU 资源让给其他线程。这里让渡的只是一个机会,不代表当前线程一定会停止,也不代表别的线程一定会执行。
七、线程中断
① 标记线程中断的位置:.interrupt()
② 判断线程是否中断:.isInterrupted()
③ 判断线程是否中断并清除中断标志:.interrupted()
八、将一个线程加入另一个线程
.join()
public class Task extends Thread{public static void main(String[] args){Thread th1=new Thread(){public void run(){System.out.println("1");}};Thread th2=new Thread(){public void run(){th1.join();System.out.println("2");}};th1.start();th2.start();}
}
本案例中,将线程 th1 加入到 th2 中,th2 会等待 th1 执行完毕之后再执行本任务中的代码。
九、守护线程
(一)设置守护线程
.setDaemon(true),将一个线程设置为主线程的守护线程,当主线程结束时,守护线程也会随之结束。
public class Task{public static void main(String[] args){Thread th=new Thread(){public void run(){while(true){System.out.println("123");} //死循环输出123}};th.setDaemon(true); //将th设置为守护线程th.start();try {Thread.sleep(500); //主线程休眠500毫秒} catch (InterruptedException e) {e.printStackTrace();}}
}
本案例中,当主线程休眠500毫秒时,子线程不断输出123;主线程500毫秒结束时,主线程执行完毕,子线程随之结束。
(二)判断守护线程
.isDaemon(),如果一个线程是守护线程,返回 true;否则返回 false。
十、判断线程是否存活
.isAlive(),线程存活的时间介于启动之后,执行完毕之前,只有在这段时间内返回 true。