Java的多线程
Java使用Thread代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用就是执行一段程序流(完成一定的任务)。
Java使用线程执行体来代表这段程序流。
1. 继承Thread类创建线程类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | package org.apache; public class ThreadDemo1 extends Thread { private int i; /* * 重写run方法,也就是线程执行体 * 当线程类继承Thread类时,直接使用this即可取得当前线程 * 直接调用getName()方法即可返回当前线程的名字 */ public void run(){ for ( ; i< 100 ;i++){ System.out.println(getName() + " " + i); } } public static void main(String[] args) { for ( int i= 0 ;i< 100 ;i++){ System.out.println(Thread.currentThread().getName() + " " +i); if (i== 20 ){ //创建并启动第一个线程 new ThreadDemo1().start(); //创建并启动第二个线程 new ThreadDemo1().start(); } } } } |
执行结果:
注意:实际上该程序有三个线程,main()方法是主线程,显示的创建了两个子线程。
Thread-0和Thread-1 i的值是不连续的,所以Thread-0和Thread-1不能共享Thread类的实例变量。
2. 实现Runnable接口创建线程类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package org.apache; public class ThreadDemo2 implements Runnable { private int i; //当实现Runnable接口时必须用Thread.currentThread().getName()获取当前线程 public void run() { for ( ; i< 100 ;i++){ System.out.println(Thread.currentThread().getName() + " " + i); } } public static void main(String[] args) { for ( int i= 0 ;i< 100 ;i++){ System.out.println(Thread.currentThread().getName() + " " +i); if (i== 20 ){ ThreadDemo2 td = new ThreadDemo2(); //通过new Thread(target,name)方法创建线程 new Thread(td, "线程1" ).start(); new Thread(td, "线程2" ).start(); } } } } |
结果:
i的值是连续的,共享同一个线程类的实例变量(其实是线程的target类)
3.使用Callable和Future创建线程
FutureTask同时实现
Future接口--->接收call()方法的返回值
和Runnable接口--->可以作为Thread的target
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /* * 创建并启动有返回值的线程步骤: * 1. 创建Callable接口的实现类,并实现call()方法,作为线程执行体 * 2. 使用FutureTask类包装Callable对象,该FutureTask对象封装了Callable对象的call()方法 * 3. 使用FutureTask对象作为Thread对象的target创建并启动新线程 * 4. 调用FutureTask对象的get()方法获得子线程的执行结束的返回值 */ public class ThreadDemo3 implements Callable{ private int i; public Object call() throws Exception { for ( ; i< 100 ;i++){ System.out.println(Thread.currentThread().getName() + " " + i); } return i; } public static void main(String[] args) { ThreadDemo3 td = new ThreadDemo3(); //通过new Thread(target,name)方法创建线程 FutureTask<Integer> task = new FutureTask<Integer>(td); for ( int i= 0 ;i< 100 ;i++){ System.out.println(Thread.currentThread().getName() + " " +i); if (i== 20 ){ new Thread(task, "有返回值的线程" ).start(); } } try {<br> //获取线程返回值 System.out.println(task.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } |
结果:
4. 控制线程
4.1 join线程
当程序程序执行流中调用其它线程的join()方法时,调用线程将会被阻塞。直到被join的线程执行完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package org.apache; public class ThreadDemo1 extends Thread { public ThreadDemo1 (String name){ super (name); } private int i; /* * 重写run方法,也就是线程执行体 * 当线程类继承Thread类时,直接使用this即可取得当前线程 * 直接调用getName()方法即可返回当前线程的名字 */ public void run(){ for ( ; i< 100 ;i++){ System.out.println(getName() + " " + i); } } public static void main(String[] args) throws InterruptedException { new ThreadDemo1( "新线程" ).start(); for ( int i= 0 ;i< 100 ;i++){ Thread task = new ThreadDemo1( "被join的线程" ); System.out.println(Thread.currentThread().getName() + " " +i); if (i== 20 ){ //创建并启动第一个线程 task.start(); //main调用了join()方法,必须等task执行结束后才会向下执行 task.join(); } } } } |
执行结果:
分析可知main方法(主线程)被阻塞,只有新线程和join线程并发执行。
4.2 守护线程
有一种线程是为其它线程提供服务的(典型的有GC),被称为后台线程或者守护线程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package org.apache; public class ThreadDemo4 extends Thread{ private int i; public void run(){ for (;i< 1000 ;i++){ System.out.println(getName() + " " +i); } } public static void main(String[] args) { ThreadDemo4 task = new ThreadDemo4(); //设置为守护进程 task.setDaemon( true ); task.start(); for ( int i= 0 ;i< 10 ;i++){ System.out.println(Thread.currentThread().getName()+ " " +i); } //程序执行到此处就main进程就结束了,JVM将会主动退出,守护线程也将被结束,无法执行到=999 } } |
执行结果:
4.3 线程睡眠:sleep
1 2 3 4 5 6 7 8 9 10 11 12 13 | package org.apache; import java.util.Date; public class ThreadDemo5 { //正在执行的线程将会暂停一段时间,进入阻塞状态 public static void main(String[] args) throws InterruptedException { for ( int i= 0 ;i< 10 ;i++){ System.out.println( "当前时间: " + new Date()); Thread.sleep( 1000 ); } } } |
结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步