哪里去找做的好看的网站,域名注册最后是网站,房地产客户管理系统,网站建设证有前言 特点分析
线程池ThreadPool 销毁线程池 Executor类 Callable接口
线程池使用 …前言 特点分析
线程池ThreadPool 销毁线程池 Executor类 Callable接口
线程池使用 Callable启动线程 ExecutorService接口的方法 前言
在上一篇Java—实现多线程程序 | 入门的文章中我们初步了解Thread类的用法
第一次书写多线程程序算是完成一个Java学习的里程碑
接下来我们继续进入多线程的学习
线程池ThreadPool
线程池线程的缓冲池目的就是提高效率。 new Thread().start(),线程是内存中的一个独立的方法栈区,JVM没有能力开辟内存空间和OS交互
而线程会频繁地与OS交互浪费资源线程池就是开辟一个空间专门用于存储线程对象可以理解为集合当线程需要时就从池子里调用出来使用结束再丢回线程池保证了线程不会“死掉”反复利用达到高效 线程池的目的是为了提高线程的利用率减少创建和销毁线程的开销降低系统资源的消耗提高系统的稳定性和可靠性。在高并发的环境中线程池可以有效地控制并发数量防止线程因互相竞争而产生死锁、饥饿或者系统资源耗尽等问题。 tips后面学到的数据库连接池也是类似的效果
jdk5开始内置线程池 Executor类
使用静态方法创建线程池
public static newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池以共享的无界队列方式来运行这些线程。
int nThreads是传入线程的数量 方法的返回值是ExecutorService接口的实现类管理池子里面的线程 线程池使用
创建线程池 线程数量是两个 线程数量虽然可以自行定义但最好不要过多浪费资源 ExecutorService es Executors.newFixedThreadPool(2);
创建线程对象线程池管理对象Service调用方法submit提交线程任务当然前提是得先写一个Runnable
public class MyRunnable implements Runnable{Overridepublic void run() {System.out.println(线程开始运行);}
}
ExecutorService接口的方法
submit(Runnable r)提交线程执行的任务
public class ThreadTest {public static void main(String[] args) {ExecutorService es Executors.newFixedThreadPool(2);Runnable runnable new MyRunnable();es.submit(runnable);}
} 特点分析
这一次运行代码不知道你们是否发现了不同之处
以往的代码运行时程序会自动结束不再运行而这次你可以看到程序一直在后台保活直到我们手动关闭。这就是上文所说线程池的作用用则拿不用则还线程不死 使用了线程池的程序 这里的中文乱码比较懒没有调整将就着看哈哈如果你也遇到了中文乱码的问题而没有找到合适的方法可以看我的另一篇文章我想它会对你有所帮助⬇⬇⬇解决IntelliJ IDEA 代码运行时中文出现乱码 同时为了更直观地看到线程的执行我们还可以查看一下线程的名字然后把runnab对象多submit几次
System.out.println(Thread.currentThread().getName()线程开始运行);
public class ThreadTest {public static void main(String[] args) {ExecutorService es Executors.newFixedThreadPool(2);Runnable runnable new MyRunnable();es.submit(runnable);es.submit(runnable);es.submit(runnable);es.submit(runnable);es.submit(runnable);}
} 查看使用中的线程名 销毁线程池
当我们不需要使用线程池时总得让它结束所以我们就可以把它销毁自行结束
es.shutdown(); 此时我们再运行程序当所有线程不再使用时运行到这行代码线程池就被销毁了 Callable接口 Callable也能像Runnable一样建线程但和Runnable接口有区别 Callable接口有返回值且Callable的call方法可以抛出异常Runnable没有 Callable的抽象方法只有一个call
我们尝试使用一下相关代码
public class MyCall implements CallableV {public V call() throws Exception {return null;}
} 注意此处的V为泛型即你需要返回数据的类型此处我们可以改成String然后return字符串
public class MyCall implements CallableString {public String call() throws Exception {return 返回字符串;}
}
Callable启动线程
线程调用重写方法call需要使用到线程池我们依旧可以使用submit把submit(Runnable r)改为submit(Callable c)提交线程执行的任务但当我们运行时没有任何输出结果
这时候我们就要使用Future接口,Future submit()方法提交线程任务后方法有个返回值Future接口类型而它则可以获取到线程执行后返回的结果
public class CallText {public static void main(String[] args) throws ExecutionException, InterruptedException {//创建线程池ExecutorService es Executors.newFixedThreadPool(2);//创建线程MyCall myCall new MyCall();//提交线程任务使用Callable接口实现类FutureString future es.submit(myCall);//返回接口类型Future//接口的方法get,获取线程的返回值String str future.get();System.out.println(str str);}
} 运行结果