Java线程个数简单控制
来源:互联网 发布:新华阅读网软件 编辑:程序博客网 时间:2024/05/17 23:39
系统在运行时,有时候我们要控制它同时允许多少个线程运行,如果太多可能引起内存溢出之类的异常,所以在线程比较多的情况下我们可以控制它的最大线程数,这样系统可以在一种比较稳定的状态下运行。下面是一个简单实现,可以少加修改用在系统中去。
- package thread;
- public class CreateThread {
- public static void main(String[] args) throws InterruptedException {
- //比如我们现要创建30个子线程,但允许最大线程数为10
- for (int i = 0; i < 30; i++) {
- // 获取锁资源
- synchronized (SubThread.class) {
- int tCount = SubThread.getThreadCounts();
- // 如果入库线程达到了最大允许的线程数
- while (tCount >= 10) {
- System.out.println("系统当前线程数为:" + tCount
- + ",已达到最大线程数 10,请等待其他线程执行完毕并释放系统资源");
- // 释放锁,等待“线程数”资源,等待其他入库线程执行完毕
- SubThread.class.wait();
- /*
- * 带条件的wait()(即放在条件语句执行的wait()方法),一定要放在while
- * 条件里执行,因为被唤醒之后该线程有可能不会马上执行,只是把当前线程从等
- * 待池中放入对象锁池队列中,直到获取到锁后才开始运行。所以在同步块里wait方
- * 法前后的代码块不是原子性的,会分开执行,但sleep()不同,睡时不会释放锁。
- * 所以等到执行时,可能条件已被其他的线程给改变了(像这里的最大线程数),此
- * 时就需要再此判断该条件,否则条件可能不成立了
- */
- tCount = SubThread.getThreadCounts();
- }
- // 重新启动一个子线程
- Thread td = new SubThread();
- td.start();
- System.out.println("已创建新的子线程: " + td.getName());
- }
- }
- }
- }
package thread;public class CreateThread {public static void main(String[] args) throws InterruptedException {//比如我们现要创建30个子线程,但允许最大线程数为10for (int i = 0; i < 30; i++) {// 获取锁资源synchronized (SubThread.class) {int tCount = SubThread.getThreadCounts();// 如果入库线程达到了最大允许的线程数while (tCount >= 10) {System.out.println("系统当前线程数为:" + tCount+ ",已达到最大线程数 10,请等待其他线程执行完毕并释放系统资源");// 释放锁,等待“线程数”资源,等待其他入库线程执行完毕SubThread.class.wait();/* * 带条件的wait()(即放在条件语句执行的wait()方法),一定要放在while * 条件里执行,因为被唤醒之后该线程有可能不会马上执行,只是把当前线程从等 * 待池中放入对象锁池队列中,直到获取到锁后才开始运行。所以在同步块里wait方 * 法前后的代码块不是原子性的,会分开执行,但sleep()不同,睡时不会释放锁。 * 所以等到执行时,可能条件已被其他的线程给改变了(像这里的最大线程数),此 * 时就需要再此判断该条件,否则条件可能不成立了 */tCount = SubThread.getThreadCounts();}// 重新启动一个子线程Thread td = new SubThread();td.start();System.out.println("已创建新的子线程: " + td.getName());}}}}
- package thread;
- public class SubThread extends Thread {
- // 线程计数器
- static private int threadCounts;
- // 线程名称池
- static private String threadNames[];
- static {
- // 假设这里允许系统同时运行最大线程数为10个
- int maxThreadCounts = 10;
- threadNames = new String[maxThreadCounts];
- // 初始化线程名称池
- for (int i = 1; i <= maxThreadCounts; i++) {
- threadNames[i - 1] = "子线程_" + i;
- }
- }
- public SubThread() {
- // 临界资源锁定
- synchronized (SubThread.class) {
- // 线程总数加1
- threadCounts++;
- // 从线程名称池中取出一个未使用的线程名
- for (int i = 0; i < threadNames.length; i++) {
- if (threadNames[i] != null) {
- String temp = threadNames[i];
- // 名被占用后清空
- threadNames[i] = null;
- // 初始化线程名称
- this.setName(temp);
- break;
- }
- }
- }
- }
- public void run() {
- System.out.println("-->>" + this.getName() + "开始运行");
- try {
- //模拟程序耗时
- Thread.sleep(1000);
- // ...
- } catch (Exception e) {
- System.out.println(e);
- } finally {
- synchronized (SubThread.class) {
- // 线程运行完毕后减1
- threadCounts--;
- // 释放线程名称
- String[] threadName = this.getName().split("_");
- // 线程名使用完后放入名称池
- threadNames[Integer.parseInt(threadName[1]) - 1] = this.getName();
- /*
- * 通知其他被阻塞的线程,但如果其他线程要执行,则该同步块一定要运行结束(即直
- * 到释放占的锁),其他线程才有机会执行,所以这里的只是唤醒在此对象监视器上等待
- * 的所有线程,让他们从等待池中进入对象锁池队列中,而这些线程重新运行时它们一定
- * 要先要得该锁后才可能执行,这里的notifyAll是不会释放锁的,试着把下面的睡眠语
- * 句注释去掉,即使你已调用了notify方法,发现CreateThread中的同步块还是好
- * 像一直处于对象等待状态,其实调用notify方法后,CreateThread线程进入了对象锁
- * 池队列中了,只要它一获取到锁,CreateThread所在线程就会真真的被唤醒并运行。
- */
- SubThread.class.notifyAll();
- // try {
- // Thread.sleep(10000);
- // } catch (InterruptedException e) {
- // e.printStackTrace();
- // }
- System.out.println("----" + this.getName() + " 所占用资源释放完毕,当前系统正在运行的子线程数:"
- + threadCounts);
- }
- System.out.println("<<--" + this.getName() + "运行结束");
- }
- }
- static public int getThreadCounts() {
- synchronized (SubThread.class) {
- return threadCounts;
- }
- }
- }
package thread;public class SubThread extends Thread {// 线程计数器static private int threadCounts;// 线程名称池static private String threadNames[];static {// 假设这里允许系统同时运行最大线程数为10个int maxThreadCounts = 10;threadNames = new String[maxThreadCounts];// 初始化线程名称池for (int i = 1; i <= maxThreadCounts; i++) {threadNames[i - 1] = "子线程_" + i;}}public SubThread() {// 临界资源锁定synchronized (SubThread.class) {// 线程总数加1threadCounts++;// 从线程名称池中取出一个未使用的线程名for (int i = 0; i < threadNames.length; i++) {if (threadNames[i] != null) {String temp = threadNames[i];// 名被占用后清空threadNames[i] = null;// 初始化线程名称this.setName(temp);break;}}}}public void run() {System.out.println("-->>" + this.getName() + "开始运行");try {//模拟程序耗时Thread.sleep(1000);// ...} catch (Exception e) {System.out.println(e);} finally {synchronized (SubThread.class) {// 线程运行完毕后减1threadCounts--;// 释放线程名称String[] threadName = this.getName().split("_");// 线程名使用完后放入名称池threadNames[Integer.parseInt(threadName[1]) - 1] = this.getName();/* * 通知其他被阻塞的线程,但如果其他线程要执行,则该同步块一定要运行结束(即直 * 到释放占的锁),其他线程才有机会执行,所以这里的只是唤醒在此对象监视器上等待 * 的所有线程,让他们从等待池中进入对象锁池队列中,而这些线程重新运行时它们一定 * 要先要得该锁后才可能执行,这里的notifyAll是不会释放锁的,试着把下面的睡眠语 * 句注释去掉,即使你已调用了notify方法,发现CreateThread中的同步块还是好 * 像一直处于对象等待状态,其实调用notify方法后,CreateThread线程进入了对象锁 * 池队列中了,只要它一获取到锁,CreateThread所在线程就会真真的被唤醒并运行。 */SubThread.class.notifyAll();//try {//Thread.sleep(10000);//} catch (InterruptedException e) {//e.printStackTrace();//}System.out.println("----" + this.getName() + " 所占用资源释放完毕,当前系统正在运行的子线程数:"+ threadCounts);}System.out.println("<<--" + this.getName() + "运行结束");}}static public int getThreadCounts() {synchronized (SubThread.class) {return threadCounts;}}}
某次运行结果:
已创建新的子线程: 子线程_1
已创建新的子线程: 子线程_2
已创建新的子线程: 子线程_3
-->>子线程_2开始运行
已创建新的子线程: 子线程_4
-->>子线程_4开始运行
已创建新的子线程: 子线程_5
已创建新的子线程: 子线程_6
-->>子线程_6开始运行
已创建新的子线程: 子线程_7
已创建新的子线程: 子线程_8
已创建新的子线程: 子线程_9
已创建新的子线程: 子线程_10
系统当前线程数为:10,已达到最大线程数 10,请等待其他线程执行完毕并释放系统资源
-->>子线程_1开始运行
-->>子线程_8开始运行
-->>子线程_10开始运行
-->>子线程_3开始运行
-->>子线程_5开始运行
-->>子线程_7开始运行
-->>子线程_9开始运行
----子线程_2 所占用资源释放完毕,当前系统正在运行的子线程数:9
已创建新的子线程: 子线程_2
系统当前线程数为:10,已达到最大线程数 10,请等待其他线程执行完毕并释放系统资源
<<--子线程_2运行结束
-->>子线程_2开始运行
----子线程_4 所占用资源释放完毕,当前系统正在运行的子线程数:9
<<--子线程_4运行结束
已创建新的子线程: 子线程_4
系统当前线程数为:10,已达到最大线程数 10,请等待其他线程执行完毕并释放系统资源
-->>子线程_4开始运行
----子线程_6 所占用资源释放完毕,当前系统正在运行的子线程数:9
<<--子线程_6运行结束
----子线程_10 所占用资源释放完毕,当前系统正在运行的子线程数:8
<<--子线程_10运行结束
----子线程_8 所占用资源释放完毕,当前系统正在运行的子线程数:7
<<--子线程_8运行结束
已创建新的子线程: 子线程_6
已创建新的子线程: 子线程_8
已创建新的子线程: 子线程_10
系统当前线程数为:10,已达到最大线程数 10,请等待其他线程执行完毕并释放系统资源
----子线程_1 所占用资源释放完毕,当前系统正在运行的子线程数:9
<<--子线程_1运行结束
-->>子线程_6开始运行
-->>子线程_10开始运行
已创建新的子线程: 子线程_1
----子线程_7 所占用资源释放完毕,当前系统正在运行的子线程数:9
<<--子线程_7运行结束
----子线程_9 所占用资源释放完毕,当前系统正在运行的子线程数:8
<<--子线程_9运行结束
-->>子线程_8开始运行
-->>子线程_1开始运行
----子线程_5 所占用资源释放完毕,当前系统正在运行的子线程数:7
<<--子线程_5运行结束
----子线程_3 所占用资源释放完毕,当前系统正在运行的子线程数:6
<<--子线程_3运行结束
已创建新的子线程: 子线程_3
已创建新的子线程: 子线程_5
-->>子线程_5开始运行
已创建新的子线程: 子线程_7
已创建新的子线程: 子线程_9
系统当前线程数为:10,已达到最大线程数 10,请等待其他线程执行完毕并释放系统资源
-->>子线程_9开始运行
-->>子线程_3开始运行
-->>子线程_7开始运行
----子线程_4 所占用资源释放完毕,当前系统正在运行的子线程数:9
<<--子线程_4运行结束
----子线程_8 所占用资源释放完毕,当前系统正在运行的子线程数:8
<<--子线程_8运行结束
----子线程_1 所占用资源释放完毕,当前系统正在运行的子线程数:7
<<--子线程_1运行结束
已创建新的子线程: 子线程_1
已创建新的子线程: 子线程_4
-->>子线程_4开始运行
已创建新的子线程: 子线程_8
-->>子线程_1开始运行
-->>子线程_8开始运行
----子线程_5 所占用资源释放完毕,当前系统正在运行的子线程数:9
<<--子线程_5运行结束
已创建新的子线程: 子线程_5
----子线程_2 所占用资源释放完毕,当前系统正在运行的子线程数:9
<<--子线程_2运行结束
----子线程_6 所占用资源释放完毕,当前系统正在运行的子线程数:8
<<--子线程_6运行结束
-->>子线程_5开始运行
----子线程_10 所占用资源释放完毕,当前系统正在运行的子线程数:7
<<--子线程_10运行结束
----子线程_9 所占用资源释放完毕,当前系统正在运行的子线程数:6
<<--子线程_9运行结束
已创建新的子线程: 子线程_2
已创建新的子线程: 子线程_6
已创建新的子线程: 子线程_9
已创建新的子线程: 子线程_10
系统当前线程数为:10,已达到最大线程数 10,请等待其他线程执行完毕并释放系统资源
-->>子线程_6开始运行
-->>子线程_10开始运行
----子线程_3 所占用资源释放完毕,当前系统正在运行的子线程数:9
已创建新的子线程: 子线程_3
系统当前线程数为:10,已达到最大线程数 10,请等待其他线程执行完毕并释放系统资源
<<--子线程_3运行结束
----子线程_7 所占用资源释放完毕,当前系统正在运行的子线程数:9
已创建新的子线程: 子线程_7
<<--子线程_7运行结束
-->>子线程_2开始运行
-->>子线程_9开始运行
-->>子线程_7开始运行
-->>子线程_3开始运行
----子线程_4 所占用资源释放完毕,当前系统正在运行的子线程数:9
<<--子线程_4运行结束
----子线程_1 所占用资源释放完毕,当前系统正在运行的子线程数:8
<<--子线程_1运行结束
----子线程_8 所占用资源释放完毕,当前系统正在运行的子线程数:7
<<--子线程_8运行结束
----子线程_5 所占用资源释放完毕,当前系统正在运行的子线程数:6
<<--子线程_5运行结束
----子线程_6 所占用资源释放完毕,当前系统正在运行的子线程数:5
<<--子线程_6运行结束
----子线程_10 所占用资源释放完毕,当前系统正在运行的子线程数:4
<<--子线程_10运行结束
----子线程_2 所占用资源释放完毕,当前系统正在运行的子线程数:3
<<--子线程_2运行结束
----子线程_7 所占用资源释放完毕,当前系统正在运行的子线程数:2
<<--子线程_7运行结束
----子线程_9 所占用资源释放完毕,当前系统正在运行的子线程数:1
<<--子线程_9运行结束
----子线程_3 所占用资源释放完毕,当前系统正在运行的子线程数:0
<<--子线程_3运行结束
- Java线程个数简单控制
- Java线程个数简单控制
- java concurrent 探秘(经典的线程个数,是否完成等的控制) 线程池
- java concurrent 探秘(经典的线程个数,是否完成等的控制) 线程池
- java concurrent 探秘(经典的线程个数,是否完成等的控制) 线程池
- Java实现控制线程超时的简单方法
- 简单入门java多线程<三>:线程控制API
- java concurrent 探秘(经典的线程个数,是否完成等的控制)
- java concurrent 探秘(经典的线程个数,是否完成等的控制)
- Java多线程程序控制线程个数
- Java--线程生命周期,线程控制
- Java.线程生命控制
- java 线程控制
- java线程控制
- Java线程并发控制
- 【Java基础】:线程控制
- Java:控制线程
- JAVA线程控制
- zoj 2423 Fractal
- td中的内容居中的办法
- bzoj 1059 题解
- <Android> Android Studio
- SVN版本控制器的普通服务器安装----->Subversion
- Java线程个数简单控制
- Splay括号匹配(BZOJ2209)
- ACM - 算法篇,基础题目
- SDJZU_新生_KMP/字符串
- Backbone.js学习记录 Hello World!
- Android原生(Native)C开发
- border-radius 移动之伤
- 最全的SDK环境下载
- Android 数据存储——SQLite使用详解