目录
前言:
多线程的实现方式:
Thread常见的成员方法:
总结:
前言:
多线程的引入不仅仅是提高计算机处理能力的技术手段,更是适应当前时代对效率和性能要求的必然选择。在本文中,我们将深入探讨多线程的应用和实践,帮助读者更好地理解和应用多线程技术,提升计算机的处理能力,迎接挑战的世界。"
多线程的实现方式:
1.继承Thread类:你可以创建一个类并继承Thread类,然后重写run()方法,在run()方法中定义线程要执行的任务。通过创建该类的实例,并调用start()方法,可以启动一个新的线程执行run()方法中的任务。
示例代码:
class MyThread extends Thread {public void run() {// 定义线程要执行的任务System.out.println("线程执行任务");}
}public class MainClass {public static void main(String[] args) {// 创建线程并启动MyThread thread = new MyThread();thread.start();}
}
2.实现Runnable接口:你可以创建一个类实现Runnable接口,然后实现run()方法,再通过创建Thread对象,并将Runnable对象作为参数传递给Thread的构造函数,创建一个新的线程。
示例代码:
class MyRunnable implements Runnable {public void run() {// 定义线程要执行的任务System.out.println("线程执行任务");}
}public class MainClass {public static void main(String[] args) {// 创建线程并启动MyRunnable runnable = new MyRunnable();Thread thread = new Thread(runnable);thread.start();}
}
3.使用Executor框架:Java提供了Executor框架,它是高级线程管理的一种方式。通过Executor,你可以使用线程池来管理和执行多个线程任务,提供更好的线程控制和资源管理。
示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class MainClass {public static void main(String[] args) {// 创建线程池ExecutorService executor = Executors.newFixedThreadPool(5);// 提交任务executor.execute(new Runnable(){public void run() {// 定义线程要执行的任务System.out.println("线程执行任务");}});// 关闭线程池executor.shutdown();}
}
4.使用Callable 和 Future 接口方式实现:当需要在线程执行完毕后获取返回结果时,可以使用Callable和Future接口来实现多线程。Callable是一个带有返回结果的任务,可以通过call()方法执行任务并返回结果。Future表示一个异步执行的任务,可以通过get()方法获取任务的返回结果。
这种方式的优点就在于:可以获取多线程的执行结果
示例代码:
class MyCallable implements Callable<Integer> {public Integer call() throws Exception {// 定义线程要执行的任务,并返回结果return 42;}
}public class MainClass {public static void main(String[] args) {// 创建线程池ExecutorService executor = Executors.newSingleThreadExecutor();// 提交Callable任务Future<Integer> future = executor.submit(new MyCallable());// 等待并获取结果try {Integer result = future.get();System.out.println("线程执行任务的结果为: " + result);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}// 关闭线程池executor.shutdown();}
}
Thread常见的成员方法:
- start(): 启动线程,使线程进入可运行状态,具体执行由操作系统调度。
- run(): 线程执行的任务代码,通常通过重写该方法来定义线程要执行的逻辑。
- sleep(long millis): 让当前线程休眠指定的毫秒数,暂停线程的执行。
- join(): 等待线程执行完成,即等待线程终止。
- yield(): 暂停当前正在执行的线程,并允许其他线程执行。
- isAlive(): 判断线程是否还活着。
- interrupt(): 中断线程,向线程发送一个中断信号,但并不一定终止线程的执行。
- isInterrupted(): 判断线程是否被中断。
- setName(String name): 设置线程的名称。
- getName(): 获取线程的名称。
- suspend(): 不推荐使用,暂停线程的执行。
- resume(): 不推荐使用,恢复线程的执行。
- setPriority(int priority): 设置线程的优先级,取值范围为1-10,默认为5。
- getPriority(): 获取线程的优先级。
- setDaemon(boolean on)设置为守护线程
我们再单独介绍一下几个常用并且不容易理解的成员方法:
1.setPriority(int priority)与
getPriority()
setPriority(int priority)
方法用于设置线程的优先级,参数priority
表示线程的优先级,取值范围为1-10,优先级默认为5。其中,1表示最低优先级,10表示最高优先级。
getPriority()
方法用于获取线程的优先级,返回值为线程的优先级。
线程的优先级用于指定线程在竞争CPU资源时的优先级顺序。然而,优先级并不是绝对的执行顺序,仅作为建议给操作系统进行线程调度。
优先级的出现是因为我们JAVA中的线程在被CPU调度的时候,采用的是抢占式调度,也就是优先级越高,越容易抢到调度机会,而除了抢占式调度之外,我们还有非抢占调度,也就是CPU对线程轮流调度,不存在随机。
需要注意以下几点:
- 不同操作系统对线程优先级的处理可能有所不同。
- 线程的优先级不能保证一定按照预期执行,因为优先级可能受到操作系统调度算法的影响。
- 不应该过分依赖线程的优先级来实现业务逻辑,因为这可能导致代码的可移植性差。
一般来说,应用程序中使用默认优先级即可,除非有特殊需求。同时,应避免过于频繁地修改线程的优先级,以免导致优先级倾斜等问题。
2.setDaemon(boolean on)
setDaemon(boolean on)
是Thread类提供的一个方法,用于设置线程的守护状态。当一个线程被设置为守护线程时,它会成为JVM中所有非守护线程的"服务员",在所有非守护线程结束后,JVM会自动退出,从而终止守护线程的执行。
具体来说,守护线程的特点如下:
- 守护线程通常用来提供后台服务或辅助功能,不影响程序的主要业务逻辑。
- 守护线程并不会影响JVM的正常终止,即使还有守护线程在执行,JVM也会自动退出。
- 当所有非守护线程结束后,守护线程会被自动终止,不会等待任务完成。
使用setDaemon(true)
将线程设置为守护线程,使用setDaemon(false)
将线程设置为用户线程(默认值)。
需要注意以下几点:
setDaemon()
方法只能在线程启动之前调用,一旦线程启动后,不能再修改守护状态。- 守护线程不能持有任何可以独占资源的锁,因为它们可能会在任何时刻被终止,这样可能导致资源不正确释放或状态不一致的问题。
- 守护线程并不保证会执行完它们的任务,因此在编写守护线程时要特别小心,确保它们不会影响到程序的正确执行。
守护线程主要用于在后台提供服务或执行一些不断运行的任务,比如垃圾回收线程、定时任务线程等。一般情况下,我们在主线程中创建的线程都是用户线程,即非守护线程。
3.join()与yield()
join()与yield()都是用于线程的控制和协作的方法。
-
join()
join()
方法用于等待调用线程完成其执行,然后再继续执行当前线程。- 在一个线程A中调用另一个线程B的
join()
方法会使当前线程A阻塞,直到线程B执行完成。 - 这通常用于多个线程之间的协作,确保某个线程在另一个线程执行完成后再继续执行。
- 如果在
join()
方法中指定了超时时间,那么当前线程将等待指定的时间,如果超时仍未完成,则继续执行。
-
yield()
yield()
方法是线程的静态方法,它让出当前线程的执行权,将其暂停,以便其他具有相同或更高优先级的线程可以执行。yield()
的作用是提高线程的执行效率和响应性。- 当一个线程调用
yield()
方法后,它会从运行状态转变为就绪状态,让出CPU执行权,然后和其他具有相同或更高优先级的线程竞争CPU资源。 - 注意,
yield()
方法并不能保证使得当前线程暂停执行,它只是提供一个提示给线程调度器,告知可以进行线程切换。
需要注意的是,join()
方法可以用于线程的协作,而yield()
方法用于线程的调度。join()
方法会阻塞线程直到目标线程执行完成,而yield()
方法会主动让出CPU执行权,使得其他线程有机会执行。
总结:
本文我们介绍了使用线程的三种方法以及线程类中的常见成员方法,多线程是处理高并发问题的一个重要手段,因此我们一定要学好多线程。
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!