在 Java 中,多线程是指同时执行两个或多个线程以最大限度地利用 CPU 的过程。 Java 中的线程是一个轻量级进程,只需要较少的资源即可创建和共享进程资源。
多线程和多进程用于 Java 中的多任务处理,但我们更喜欢多线程而不是多进程。 这是因为线程使用共享内存区域有助于节省内存,而且线程之间的内容切换比进程快一点。
线程的生命周期
线程在其生命周期中必须经历五种状态。 此生命周期由 JVM(Java 虚拟机)控制。 这些状态是:
NewRunnableRunningNon-Runnable (Blocked)Terminated
New
在这种状态下,一个新线程开始它的生命周期。 这也称为新生线程。 如果在调用 start() 方法之前创建 Thread 类的实例,则线程处于新创建状态。
Runnable
一个线程在一个新生成的线程启动后变为可运行的。 在这种状态下,线程将执行其任务。
Running
当线程调度程序选择线程时,该线程将处于运行状态。
Non-Runnable (Blocked)
该线程在此状态下仍处于活动状态,但目前还没有资格运行。
Terminated
线程因以下原因而终止:
它的 run() 方法要么正常存在,即线程的代码已经执行了程序。或者由于一些不寻常的错误,如分段错误或未处理的异常。
处于终止状态的线程不会消耗 CPU 的任何周期。
Java线程类
Java Thread 类提供了在线程上创建和执行操作的方法和构造函数。 Java 线程类扩展了 Object 类并实现了 Runnable 接口。
Java Thread方法
这些是 Thread 类中可用的方法:
1. public void start()
它开始执行线程,然后在这个 Thread 对象上调用 run()。
示例:
{public void run() {System.out.println("Thread is running..."); } public static void main(String[] args) {StartExp1 thread1=new StartExp1();thread1.start(); } }
输出
Thread is running…
2. public void run()
该线程用于为线程执行操作。 如果线程是使用单独的 Runnable 对象构造的,则实例化 run() 方法。
示例
public class RunExp1 implements Runnable {public void run() {System.out.println("Thread is running..."); } public static void main(String args[]) {RunExp1 r1=new RunExp1(); Thread thread1 =new Thread(r1); thread1.start(); } }
输出
Thread is running…
2. public void sleep()
这会在指定的时间内阻塞当前正在运行的线程。
示例
public class SleepExp1 extends Thread {public void run() {for(int i=1;i<5;i++) {try {Thread.sleep(500); }catch(InterruptedException e){System.out.println(e);} System.out.println(i); } } public static void main(String args[]) {SleepExp1 thread1=new SleepExp1(); SleepExp1 thread2=new SleepExp1(); thread1.start(); thread2.start(); } }
输出
1
1
2
2
3
3
4
4
4. public static Thread currentThread()
它返回对当前正在运行的线程的引用。
示例
public class CurrentThreadExp extends Thread {public void run() {System.out.println(Thread.currentThread().getName()); } public static void main(String args[]) {CurrentThreadExp thread1=new CurrentThreadExp(); CurrentThreadExp thread2=new CurrentThreadExp(); thread1.start(); thread2.start(); } }
输出
Thread-0
Thread-1
5. public void join()
它会导致当前线程阻塞,直到第二个线程终止或经过指定的毫秒数。
示例
public class JoinExample1 extends Thread {public void run() {for(int i=1; i<=4; i++) {try {Thread.sleep(500); }catch(Exception e){System.out.println(e);} System.out.println(i); } } public static void main(String args[]) {JoinExample1 thread1 = new JoinExample1(); JoinExample1 thread2 = new JoinExample1(); JoinExample1 thread3 = new JoinExample1(); thread1.start(); try {thread1.join(); }catch(Exception e){System.out.println(e);} thread2.start(); thread3.start(); } }
输出
1
2
3
4
1
1
2
2
3
3
4
4
6. public final int getPriority()
它用于检查线程的优先级。 创建线程时,会为其分配一些优先级。 此优先级由 JVM 或程序员在创建线程时显式分配。
示例
public class JavaGetPriorityExp extends Thread {public void run() {System.out.println("running thread name is:"+Thread.currentThread().getName()); } public static void main(String args[]) {JavaGetPriorityExp t1 = new JavaGetPriorityExp(); JavaGetPriorityExp t2 = new JavaGetPriorityExp(); System.out.println("t1 thread priority : " + t1.getPriority()); System.out.println("t2 thread priority : " + t2.getPriority()); t1.start(); t2.start(); } }
输出
t1 thread priority : 5
t2 thread priority : 5
running thread name is:Thread-0
running thread name is:Thread-1
7. public final void setPriority()
此方法用于更改线程的优先级。 每个线程的优先级由 1 到 10 的整数表示。线程的默认优先级为 5。
示例
public class JavaSetPriorityExp1 extends Thread {public void run() {System.out.println("Priority of thread is: "+Thread.currentThread().getPriority()); } public static void main(String args[]) {JavaSetPriorityExp1 t1=new JavaSetPriorityExp1();t1.setPriority(Thread.MAX_PRIORITY); t1.start(); } }
输出
Priority of thread is: 10
8. public final String getName()
线程类的这个方法用于返回线程的名称。 我们不能在我们的程序中覆盖这个方法,因为这个方法是final的。
示例
public class GetNameExample extends Thread {public void run() {System.out.println("Thread is running..."); } public static void main(String args[]) {// creating two threads GetNameExample thread1=new GetNameExample(); GetNameExample thread2=new GetNameExample(); System.out.println("Name of thread1: "+ thread1.getName()); System.out.println("Name of thread2: "+thread2.getName()); thread1.start(); thread2.start(); } }
输出
Name of thread1: Thread-0
Name of thread2: Thread-1
Thread is running…
Thread is running…
9. public final void setName()
此方法更改线程的名称。
示例
public class SetNameExample extends Thread {public void run() {System.out.println("running..."); } public static void main(String args[]) {SetNameExample thread1=new SetNameExample(); SetNameExample thread2=new SetNameExample(); thread1.start(); thread2.start(); thread1.setName("Kadamb Sachdeva"); thread2.setName("Great learning"); System.out.println("After changing name of thread1: "+thread1.getName()); System.out.println("After changing name of thread2: "+thread2.getName()); } }
输出
After changing name of thread1: Kadamb Sachdeva
After changing name of thread2: Great Learning
running…
running…
10. public long getId()
它返回线程的标识符。 线程 ID 是创建线程时生成的数字。 此 ID 在其生命周期内无法更改。 但是当线程终止时,ID可以被重用。
示例
public class GetIdExample extends Thread {public void run() {System.out.println("running..."); } public static void main(String args[]) {GetIdExample thread1=new GetIdExample(); System.out.println("Name of thread1: "+thread1.getName()); System.out.println("Id of thread1: "+thread1.getId()); thread1.start(); } }
输出
Name of thread1: Thread-0
Id of thread1: 21
running…
11. public final boolean isAlive()
此方法检查线程是否处于活动状态。 如果线程类的 start() 方法已被调用且线程尚未死亡,则线程处于活动状态。
示例
public class JavaIsAliveExp extends Thread {public void run() {try {Thread.sleep(300); System.out.println("is run() method isAlive "+Thread.currentThread().isAlive()); } catch (InterruptedException ie) {} } public static void main(String[] args) {JavaIsAliveExp thread1 = new JavaIsAliveExp(); System.out.println("before starting thread isAlive: "+thread1.isAlive()); thread1.start(); System.out.println("after starting thread isAlive: "+thread1.isAlive()); } }
输出
before starting thread isAlive: false
after starting thread isAlive: true
is run() method isAlive true
12. public static void yield()
该方法暂停当前线程的执行以暂时执行其他线程。
示例
public class JavaYieldExp extends Thread {public void run() {for (int i=0; i<3 ; i++) System.out.println(Thread.currentThread().getName() + " in control"); } public static void main(String[]args) {JavaYieldExp thread1 = new JavaYieldExp(); JavaYieldExp thread2 = new JavaYieldExp(); thread1.start(); thread2.start(); for (int i=0; i<3; i++) {thread1.yield(); System.out.println(Thread.currentThread().getName() + " in control"); } } }
输出
main in control
main in control
main in control
Thread-0 in control
Thread-0 in control
Thread-0 in control
Thread-1 in control
Thread-1 in control
Thread-1 in control
13. public final void suspend()
该方法用于暂时挂起当前正在运行的线程。 使用 resume() 方法,您可以恢复挂起的线程。
示例
public class JavaSuspendExp extends Thread {public void run() {for(int i=1; i<5; i++) {try {sleep(500); System.out.println(Thread.currentThread().getName()); }catch(InterruptedException e){System.out.println(e);} System.out.println(i); } } public static void main(String args[]) {JavaSuspendExp thread1=new JavaSuspendExp (); JavaSuspendExp thread2=new JavaSuspendExp (); JavaSuspendExp thread3=new JavaSuspendExp ();thread1.start(); thread2.start(); thread2.suspend(); thread3.start(); } }
输出
Thread-0
1
Thread-2
1
Thread-0
2
Thread-2
2
Thread-0
3
Thread-2
3
Thread-0
4
Thread-2
4
14. public final void resume()
此方法用于恢复挂起的线程。 它仅与 suspend() 方法一起使用。
public class JavaResumeExp extends Thread {public void run() {for(int i=1; i<5; i++) {try {sleep(500); System.out.println(Thread.currentThread().getName()); }catch(InterruptedException e){System.out.println(e);} System.out.println(i); } } public static void main(String args[]) {JavaResumeExp thread1=new JavaResumeExp (); JavaResumeExp thread2=new JavaResumeExp (); JavaResumeExp thread3=new JavaResumeExp (); thread1.start(); thread2.start(); thread2.suspend();thread3.start(); thread2.resume();} }
输出
Thread-0
1
Thread-2
1
Thread-1
1
Thread-0
2
Thread-2
2
Thread-1
2
Thread-0
3
Thread-2
3
Thread-1
3
Thread-0
4
Thread-2
4
Thread-1
4
15. public final void stop()
顾名思义,此方法用于停止当前正在运行的线程。 请记住,一旦线程执行停止,就无法重新启动。
示例
public class JavaStopExp extends Thread {public void run() {for(int i=1; i<5; i++) {try {sleep(500); System.out.println(Thread.currentThread().getName()); }catch(InterruptedException e){System.out.println(e);} System.out.println(i); } } public static void main(String args[]) {JavaStopExp thread1=new JavaStopExp (); JavaStopExp thread2=new JavaStopExp (); JavaStopExp thread3=new JavaStopExp (); thread1.start(); thread2.start(); thread3.stop(); System.out.println("Thread thread3 is stopped"); } }
16. public void destroy()
此线程方法会破坏线程组及其子组。
示例
public class JavaDestroyExp extends Thread {JavaDestroyExp(String threadname, ThreadGroup tg) {super(tg, threadname); start(); } public void run() {for (int i = 0; i < 2; i++) {try {Thread.sleep(10); } catch (InterruptedException ex) {System.out.println("Exception encounterted");} } System.out.println(Thread.currentThread().getName() + " finished executing"); } public static void main(String arg[]) throws InterruptedException, SecurityException {ThreadGroup g1 = new ThreadGroup("Parent thread"); ThreadGroup g2 = new ThreadGroup(g1, "child thread"); JavaDestroyExp thread1 = new JavaDestroyExp("Thread-1", g1); JavaDestroyExp thread2 = new JavaDestroyExp("Thread-2", g1); thread1.join(); thread2.join(); g2.destroy(); System.out.println(g2.getName() + " destroyed"); g1.destroy(); System.out.println(g1.getName() + " destroyed"); } }
输出
Thread-1 finished executing
Thread-2 finished executing
child thread destroyed
Parent thread destroyed
17. public final boolean isDaemon()
此线程方法将检查线程是否为守护线程。 如果是守护线程,则返回true,否则返回false。
对于不了解守护线程的人来说,守护线程是在程序结束时不会阻止 Java 虚拟机 (JVM) 退出但线程仍在运行的线程。
示例
public class JavaIsDaemonExp extends Thread {public void run() {//checking for daemon thread if(Thread.currentThread().isDaemon()) {System.out.println("daemon thread work"); } else {System.out.println("user thread work"); } } public static void main(String[] args) {JavaIsDaemonExp thread1=new JavaIsDaemonExp(); JavaIsDaemonExp thread2=new JavaIsDaemonExp(); JavaIsDaemonExp thread3=new JavaIsDaemonExp(); thread1.setDaemon(true); thread1.start(); thread2.start(); thread3.start(); } }
输出
daemon thread work
user thread work
user thread work
18. public final void setDaemon(boolean on)
线程的这种方法用于标识或标记线程是守护进程还是用户线程。 当所有用户线程都死掉时,JVM 会自动终止该线程。
该线程方法必须在线程开始执行之前运行。
示例
public class JavaSetDaemonExp1 extends Thread {public void run() {if(Thread.currentThread().isDaemon()) {System.out.println("daemon thread work"); } else {System.out.println("user thread work"); } } public static void main(String[] args) {JavaSetDaemonExp1 thread1=new JavaSetDaemonExp1(); JavaSetDaemonExp1 thread2=new JavaSetDaemonExp1(); JavaSetDaemonExp1 thread3=new JavaSetDaemonExp1(); thread1.setDaemon(true); thread1.start(); thread2.setDaemon(true); thread2.start(); thread3.start(); } }
输出
daemon thread work
daemon thread work
user thread work
19. public void interrupt()
线程的这种方法用于中断当前正在执行的线程。 该方法只能在线程处于睡眠或等待状态时调用。
但是如果线程不处于睡眠或等待状态,那么interrupt()方法不会中断线程,而是将中断标志设置为true。
示例
public class JavaInterruptExp1 extends Thread {public void run() {try {Thread.sleep(1000); System.out.println("javatpoint"); }catch(InterruptedException e){throw new RuntimeException("Thread interrupted..."+e); } } public static void main(String args[]) {JavaInterruptExp1 thread1=new JavaInterruptExp1(); thread1.start(); try {thread1.interrupt(); }catch(Exception e){System.out.println("Exception handled "+e);} } }
输出
Exception in thread “Thread-0” java.lang.RuntimeException: Thread interrupted…java.lang.InterruptedException: sleep interrupted at JavaInterruptExp1.run(JavaInterruptExp1.java:10)
20. public boolean isInterrupted()
该线程方法用于测试线程是否被中断。 它将内部标志的值作为真或假返回,即如果线程被中断,它将返回真,否则返回假。
示例
public class JavaIsInterruptedExp extends Thread {public void run() {for(int i=1;i<=3;i++) {System.out.println("doing task....: "+i); } } public static void main(String args[])throws InterruptedException {JavaIsInterruptedExp thread1=new JavaIsInterruptedExp(); JavaIsInterruptedExp thread2=new JavaIsInterruptedExp(); thread1.start(); thread2.start(); System.out.println("is thread interrupted..: "+thread1.isInterrupted()); System.out.println("is thread interrupted..: "+thread2.isInterrupted()); thread1.interrupt(); System.out.println("is thread interrupted..: " +thread1.isInterrupted()); System.out.println("is thread interrupted..: "+thread2.isInterrupted()); } }
输出
is thread interrupted…: false
is thread interrupted…: false
is thread interrupted…: true
is thread interrupted…: false
doing task….: 1
doing task….: 2
doing task….: 3
doing task….: 1
doing task….: 2
doing task….: 3
21. public static boolean interrupted()
该线程方法用于检查当前线程是否被中断。 如果要连续调用此线程方法两次,则第二次调用将返回 false。
如果线程的中断状态为真,那么这个线程方法会将其设置为假。
示例
public class JavaInterruptedExp extends Thread {public void run() {for(int i=1;i<=3;i++) {System.out.println("doing task....: "+i); } } public static void main(String args[])throws InterruptedException {JavaInterruptedExp thread1=new JavaInterruptedExp(); JavaInterruptedExp thread2=new JavaInterruptedExp(); thread1.start(); thread2.start(); System.out.println("is thread thread1 interrupted..:"+thread1.interrupted()); thread1.interrupt(); System.out.println("is thread thread1 interrupted..:"+thread1.interrupted()); System.out.println("is thread thread2 interrupted..:"+thread2.interrupted()); } }
输出
is thread thread1 interrupted…: false
is thread thread1 interrupted…: false
is thread thread2 interrupted…: false
doing task….: 1
doing task….: 2
doing task….: 3
doing task….: 1
doing task….: 2
doing task….: 3
22. public static int activeCount()
线程的这个方法用于返回当前执行线程的线程组中的活动线程数。
此线程方法返回的数字只是一个估计数字,因为此方法遍历内部数据结构时线程数会动态变化。
示例
public class JavaActiveCountExp extends Thread {JavaActiveCountExp(String threadname, ThreadGroup tg) {super(tg, threadname); start(); } public void run() {System.out.println("running thread name is:"+Thread.currentThread().getName()); } public static void main(String arg[]) {ThreadGroup g1 = new ThreadGroup("parent thread group"); JavaActiveCountExp thread1 = new JavaActiveCountExp("Thread-1", g1); JavaActiveCountExp thread2 = new JavaActiveCountExp("Thread-2", g1); System.out.println("number of active thread: "+ g1.activeCount()); } }
输出
number of active thread: 2
running thread name is: Thread-1
running thread name is: Thread-2
23. public final void checkAccess()
该线程方法标识当前线程是否具有修改线程的权限。
示例
public class JavaCheckAccessExp extends Thread{public void run() {System.out.println(Thread.currentThread().getName()+" finished executing"); } public static void main(String arg[]) throws InterruptedException, SecurityException {JavaCheckAccessExp thread1 = new JavaCheckAccessExp(); JavaCheckAccessExp thread2 = new JavaCheckAccessExp(); thread1.start(); thread2.start(); thread1.checkAccess(); System.out.println(t1.getName() + " has access"); thread2.checkAccess(); System.out.println(t2.getName() + " has access"); } }
输出
Thread-0 has access
Thread-1 has access
Thread-0 finished executing
Thread-1 finished executing
24. public static boolean holdsLock(Object obj)
此线程方法检查当前执行的线程是否持有指定对象的监视器锁。 如果是这样,那么这个线程方法将返回 true。
示例
public class JavaHoldLockExp implements Runnable {public void run() {System.out.println("Currently executing thread is: " + Thread.currentThread().getName()); System.out.println("Does thread holds lock? " + Thread.holdsLock(this)); synchronized (this) {System.out.println("Does thread holds lock? " + Thread.holdsLock(this)); } } public static void main(String[] args) {JavaHoldLockExp g1 = new JavaHoldLockExp(); Thread thread1 = new Thread(g1); thread1.start(); } }
输出
Currently executing thread is: Thread-0
Does thread holds lock? false
Does thread holds lock? true
除此之外,还有多种线程方法用于不同的任务和目的。 这些线程方法如下:
public static void dumpStack()public StackTraceElement[] getStackTrace()public static int enumerate(Thread[] tarray)public Thread.State getState()public final ThreadGroup getThreadGroup()public String toString()public final void notify()public final void notifyAll()public void setContextClassLoader(ClassLoader cl)public ClassLoader getContextClassLoader()public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
创建线程
在 Java 中使用多线程时,您可以使用两种方式创建线程:
通过扩展 Thread 类通过实现 Runnable 接口
什么是Thread类
Thread 类提供了在线程上创建和执行操作的方法和构造函数。 Thread 类扩展了 Object 类并实现了 Runnable 接口。
Thread类中使用了各种构造函数,但常用的构造函数有:
Thread()Thread(String name)Thread(Runnable r)Thread(Runnable r,String name)
此外,如前所述,有多种线程方法用于不同的目的和任务。
因此,这些构造函数和方法是由 Thread 类提供的,用于在线程上执行各种操作。
Runnable接口是什么
Runnable 接口被实现,其实例旨在由线程执行。 它只有一种方法 run()。
public void run()这用于为线程执行操作。
启动一个线程
在 Java 中进行多线程时,要启动一个新创建的线程,使用 start() 方法。
一个新线程开始(使用新的调用堆栈)。线程从 New 状态移动到 Runnable 状态。当线程有机会执行时,它的目标 run() 方法将运行。
通过扩展 Thread 类的 Java Thread 示例
class Multi extends Thread{public void run(){System.out.println("thread is running..."); } public static void main(String args[]){Multi thread1=new Multi(); thread1.start(); } }
输出
thread is running…
通过实现 Runnable 接口的 Java 线程示例
class Multi3 implements Runnable{public void run(){System.out.println("thread is running..."); } public static void main(String args[]){Multi3 m1=new Multi3(); Thread thread1 =new Thread(m1); thread1.start(); } }
输出
thread is running…