一、线程创建
使用Runnable接口来创建一个新的线程:
public class Demo_1_work implements Runnable{
@Override
public void run(){
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName()+" is now running");
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String args[]){
Demo_1_work myThread1 = new Demo_1_work();
Thread thread = new Thread(myThread1);
thread.start();
}
}
这里使用类Demo_1_work来实现了Runnable接口
并且重写了runnable的run方法
在这个方法中定义我们创建的线程需要执行的逻辑
在这里是每隔一秒打印当前线程正在运行的信息
并且:如果在线程休眠期间该线程被中断,则会抛出 InterruptedException
异常,需要捕获并处理它
最后在主线程中启动该线程
不过另外更常用的是——>
通过继承Thread类创建线程:
public class Demo_1_work extends Thread{
@Override
public void run(){
//线程任务逻辑:
for(int i = 0;i < 5; i++){
System.out.println(Thread.currentThread().getName()+" is now running.");
try{
Thread.sleep(1000); //休眠1秒
}catch (InterruptedException e){
e.printStackTrace(); //捕获线程中断错误信息
}
}
}
public static void main(String args[]){
Demo_1_work demo = new Demo_1_work();
demo.start(); //启动线程
}
}
运行:
Thread类是Java lang包内的一个重要的类,可以创建线程、操作线程
Thread
类的主要方法包括:
start()
: 启动线程并执行线程的run()
方法。run()
: 线程执行的任务逻辑,需要通过重写此方法来定义线程的行为。sleep(long millis)
: 使当前线程休眠指定的毫秒数。join()
: 等待线程执行完毕。interrupt()
: 中断线程。isAlive()
: 判断线程是否还活着(是否已经启动但尚未终止)。
二、线程中断
通过调用 interrupt()
方法来中断线程。线程中断是一种通知线程停止正在执行的任务并终止执行的机制。当一个线程被中断时,它会收到一个中断信号,并有机会处理这个中断信号
public class Demo_1_work extends Thread{
@Override
public void run(){
while (!isInterrupted()){ //任务逻辑中检查线程是否被中断
//线程任务逻辑:
for(int i = 0;i < 5; i++){
System.out.println(Thread.currentThread().getName()+" is now running.");
try{
Thread.sleep(1000); //休眠1秒
}catch (InterruptedException e){
e.printStackTrace(); //捕获线程中断错误信息
System.out.println("Thread now is interrupted !");
return;
}
}
if(isInterrupted()){
System.out.println("Thread now is interrupted !");
break;//如果中断发生则退出循环
}
}
}
public static void main(String args[]){
Demo_1_work demo = new Demo_1_work();
demo.start(); //启动线程
//设定一段时间后中断线程
try{
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
demo.interrupt(); //中断线程
}
}
运行:
继续使用继承了Thread类创建的线程
但这次在任务逻辑上套了一个while循环通过isInterrupted方法来检查任务是否被中断
捕获到错误信息之后停止执行run()中的代码
并且显示一条线程被中断的信息
主程序中使用Thread类的sleep方法模拟线程延时的效果
最后通过实体demo执行线程中断方法
于是就出现了:
线程逻辑在三秒内每一秒打印了一条线程正在执行的信息
然后被中断,打印错误信息
最后返回线程被中断信息
三、线程等待
在Java中,线程等待是指一个线程等待另一个线程完成其执行。在多线程编程中,有时需要确保某个线程在另一个线程执行完毕后再继续执行。这时可以使用 join()
方法来实现线程等待
创建20个线程,每个线程打印个数,最后等所有线程执行完,返回线程执行完毕信息:
示例:
public class Demo_1_work extends Thread{
public static void main(String args[]){
Thread[] threads = new Thread[20]; //创建20条线程
for(int i = 0; i < 20; i++){
final int number = i;
//使用lamdba表达式,创建新线程
threads[i] = new Thread(()->{
System.out.println(Thread.currentThread().getName()+":"+number);
});
threads[i].start();//启动线程
}
//等待所有线程执行完毕:
for(Thread thread: threads){
try{
thread.join();
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println("All thread is now terminated.");
}
}
运行结果:
这个程序通过join方法实现了使每个执行完毕的线程等待其他线程的效果
如果我们将join方法去掉
会出现:
所有线程执行完毕的信息先于其他线程的信息出现
这说明:
当主线程执行完毕时,仍然存在其他线程未执行完毕
换句话说:
这几个线程没执行完就执行了
打印“All thread is now terminated.”信息的语句
这部分遍历每个线程检查,执行完毕后等待
四、线程休眠
这个效果在上面的例子中已经展示过,通过sleep方法让线程休眠从而达到延时执行run方法内逻辑的效果
public class Demo_1_work extends Thread{
public static void main(String args[]){
Thread[] threads = new Thread[20]; //创建20条线程
for(int i = 0; i < 20; i++){
final int number = i;
//使用lamdba表达式,创建新线程
threads[i] = new Thread(()->{
System.out.println(Thread.currentThread().getName()+":"+number);
try{ //每次打印线程信息时延时1秒
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
});
threads[i].start();//启动线程
}
//等待所有线程执行完毕:
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("All thread is now terminated.");
}
}
还是上面那个例子
使用sleep方法在每条线程打印信息时延时1秒
对sleep方法的补充:
- 调用
sleep()
方法时,当前线程会暂停执行,但不会释放任何锁。sleep()
方法抛出InterruptedException
异常,如果线程在休眠过程中被中断,则会立即抛出该异常。sleep()
方法的参数是以毫秒为单位的休眠时间,可以指定任意非负整数。sleep()
方法也可以接受一个额外的参数,表示纳秒级别的时间。
五、获取线程实例
获取线程实例,使用 Thread.currentThread()
方法。这个方法返回当前正在执行的线程的引用
在上面的例子中,程序输出每条线程信息时就使用了Thread.currentThread()
方法中的getName方法来获取当前线程实例的名称
再用printlin打印出来