信号量Semaphore,类似于锁的功能,用于多线程中对一组资源的控制。

  acquire方法用于尝试获取一个资源,未获取前将一直等待。release用于释放一个资源,release的前提是已经获得了一个资源。 

package multiThread;

import java.util.concurrent.Semaphore;

public class SemaphoreTest {
public static void main(String [ ] args) { int N = 8; //工人数 Semaphore semaphore = new Semaphore(5); //机器数目 for (int i = 1; i < N; i++) new Worker(i, semaphore).start(); } static class Worker extends Thread { private int num; private Semaphore semaphore; public Worker(int num, Semaphore semaphore) { this.num = num; this.semaphore = semaphore; } @Override
public void run() { try { semaphore.acquire(); System.out.println("工人" + this.num + "占用一个机器在生产..."); Thread.sleep(2000); System.out.println("工人" + this.num + "释放出机器"); semaphore.release(); }
catch (InterruptedException e) { e.printStackTrace(); } } } }

  运行的结果为:

工人1占用一个机器在生产...
工人3占用一个机器在生产...
工人2占用一个机器在生产...
工人4占用一个机器在生产...
工人5占用一个机器在生产...
工人3释放出机器
工人2释放出机器
工人6占用一个机器在生产...
工人4释放出机器
工人1释放出机器
工人5释放出机器
工人7占用一个机器在生产...
工人6释放出机器
工人7释放出机器

  如果在获取资源的过程中不希望一直等待,也可以使用下面的方法判断是否能获取资源。

  tryAcquire(),尝试获取一个许可,若获取成功,则立即返回true,若获取失败,则立即返回false。

  tryAcquire(long timeout, TimeUnit unit),尝试获取一个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false。

  Thread的run方法是不抛出任何检查型异常(checked exception)的,但是它自身却可能因为一个异常而被终止,导致这个线程的终结。最麻烦的是,在线程中抛出的异常即使使用try...catch也无法截获,因此可能导致一些问题出现,比如异常的时候无法回收一些系统资源,或者没有关闭当前的连接等等。
  如果程序里面使用了多线程技术的话!就需要对子线程的异常做出特殊的处理,如果没有做特殊处理的话,好像子线程的异常不会抛给主线程,有时会直接在客户端抛出异常(这当然不是我们想要的),更夸张的是,有时直接把程序给强制关闭了!
  如下面的例子,即使main线程中加上了try-catch也无法捕获子线程抛出的异常:

package multiThread.exception;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ExceptionThread implements Runnable{ @Override
public void run() {
throw new RuntimeException();
} public static void main(String [ ] args) {
try {
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ExceptionThread());
}
catch (Exception e) {
e.printStackTrace();
}
} }

  输出为:

Exception in thread "pool-1-thread-1" java.lang.RuntimeException
at multiThread.exception.ExceptionThread.run(ExceptionThread.java:10)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

  可以创建线程时绑定UncaughtExceptionHandler,UncaughtExceptionHandler的uncaughtException方法会在线程死亡前被调用。

package multiThread.exception;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; class ExceptionThread2 implements Runnable{
@Override
public void run() {
System.out.println("eh = " + Thread.currentThread().getUncaughtExceptionHandler());
throw new RuntimeException();
}
} class MyUncaughtExceptionHandler implements UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.getName() + " caught " + e);
}
} class HandlerFactory implements ThreadFactory{
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
return t;
} } public class CaptureUncaughtException { public static void main(String [ ] args) {
ExecutorService exec = Executors.newCachedThreadPool(new HandlerFactory());
exec.execute(new ExceptionThread2());
}
}

  输出结果为:

eh = multiThread.exception.MyUncaughtExceptionHandler@3ec5bfc8
Thread-0 caught java.lang.RuntimeException

  上面的例子是使用HandlerFactory为每一个线程加上了UncaughtExceptionHandler,也可以不使用HandlerFactory直接为线程加上UncaughtExceptionHandler。

  

  

Java多线程基础(二)的更多相关文章

  1. java多线程基础(二)--java多线程的基本使用

    java多线程的基本使用 在java中使用多线程,是通过继承Thread这个类或者实现Runnable这个接口或者实现Callable接口来完成多线程的. 下面是很简单的例子代码: package c ...

  2. Java 多线程基础(十二)生产者与消费者

    Java 多线程基础(十二)生产者与消费者 一.生产者与消费者模型 生产者与消费者问题是个非常典型的多线程问题,涉及到的对象包括“生产者”.“消费者”.“仓库”和“产品”.他们之间的关系如下: ①.生 ...

  3. [转]Java多线程干货系列—(一)Java多线程基础

    Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...

  4. Java多线程基础:进程和线程之由来

    转载: Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够 ...

  5. Java 多线程——基础知识

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  6. Java多线程(二)关于多线程的CPU密集型和IO密集型这件事

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  7. 1、Java多线程基础:进程和线程之由来

    Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够融会贯通 ...

  8. Java 多线程基础(一)基本概念

    Java 多线程基础(一)基本概念 一.并发与并行 1.并发:指两个或多个事件在同一个时间段内发生. 2.并行:指两个或多个事件在同一时刻发生(同时发生). 在操作系统中,安装了多个程序,并发指的是在 ...

  9. Java 多线程基础(三) start() 和 run()

    Java 多线程基础(三) start() 和 run() 通过之前的学习可以看到,创建多线程过程中,最常用的便是 Thread 类中的 start() 方法和线程类的 run() 方法.两个方法都包 ...

随机推荐

  1. [51nod1254]最大子段和 V2

    N个整数组成的序列a[1],a[2],a[3],-,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...

  2. SDP(1):ScalikeJDBC-基本操作介绍

    简单来说:JDBC是一种开放标准的跨编程语言.跨数据库类型编程API.各类型数据库产品厂商都会按它的标准要求来提供针对自身产品的JDBC驱动程序.最主要的这是一套成熟的工具,在编程人员中使用很普及.既 ...

  3. NopCommerce用core重写ef

    最近看了NopCommerce源码,用core学习着写了一个项目,修改的地方记录下.项目地址 NopCommerce框架出来好久了.18年的第一季度 懒加载出来后也会全部移动到.net core.那么 ...

  4. 关于HTTP请求出现 405状态码 not allowed的解决办法

    最近学爬虫.发现httppost请求目标网站会出现405 状态码,原因为 Apache.IIS.Nginx等绝大多数web服务器,都不允许静态文件响应POST请求 所以将post请求改为get请求即可

  5. vi命令加行号查找替换等命令

    一.加行号           : set nu二.vi查找:    当你用vi打开一个文件后,因为文件太长,如何才能找到你所要查找的关键字呢?在vi里可没有菜单-〉查找,              ...

  6. libpng+VS2012(VS2015)的使用

    OpenCV保存PNG图像底层调用的就是libpng库,简要说一下libPNG库的单独使用. 1.首先需要下载两个库,一个是libpng,一个是zlib libpng库下载地址:http://www. ...

  7. respondsToSelector

    SEL sel = @selector (start:) ; // 指定action if ([obj respondsToSelector:sel]) { //判断该对象是否有相应的方法 [obj  ...

  8. CPU频率

    CPU频率 CPU频率,就是CPU的时钟频率,简单说是CPU运算时的工作的频率(1秒内发生的同步脉冲数)的简称. 概念 CPU频率,就是CPU的时钟频率,简单说是CPU运算时的工作的频率(1秒内发生的 ...

  9. java学习总结之文件操作--ByteArrayOutputStream的用法

    ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区, 然后利用ByteArrayOutputStream和ByteArrayInputStream ...

  10. Centos7 开放防火墙端口命令

    Centos 7 使用firewalld代替了原来的iptables,使用方法如下: >>>关闭防火墙 systemctl stop firewalld.service       ...