`
jianchen
  • 浏览: 334367 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java基础复习(14)--java并发

阅读更多

并发:

 

冒泡排序:

SimpleThreadExceptionHandler.java:

 

package testthread;
public class SimpleThreadExceptionaHandler implements Thread.UncaughtExceptionHandler{
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("into this method");
       System.err.printf("%s : %s at line %d of %s\n",
               t.getName(),
               e.toString(),
               e.getStackTrace()[0].getLineNumber(),
               e.getStackTrace()[0].getFileName()
               );
    }
}

BubbleSortThread.java
package testthread;
public class BubbleSortThread extends Thread {
    private int[] numbers;
    public BubbleSortThread(int[] numbers) {
        this.setName("BubbleSortThread");
        setDefaultUncaughtExceptionHandler(new SimpleThreadExceptionaHandler());
        this.numbers = numbers;
    }
    //冒泡排序,两层循环
    @Override
    public void run() {
        int index = numbers.length;
        boolean finished = false;
        while (!finished) {
            finished = true;
            index--;
            for (int i = 0; i < index; i++) {
                if (numbers[i] < 0) {
                    throw new IllegalArgumentException("can't pass into a negative number");
                }
                //swap
                int temp = 0;
                if(numbers[i]>numbers[i+1]){
                    temp = numbers[i+1];
                    numbers[i+1]=numbers[i];
                    numbers[i]=temp;
                    finished = false;
                }
            }
        }
    }
    public int[] getNumbers(){
        return this.numbers;
    }
}
 

 测试类:

 

package testthread;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main {
    public static void main(String[] args) {
        int[] posNumbers = new int[]{5, 4, 3, 2, 1};
        int[] negNumbers = new int[]{-3, -1, -5, -2, -7};
        BubbleSortThread b1 = new BubbleSortThread(posNumbers);
        BubbleSortThread b2 = new BubbleSortThread(negNumbers);
        try {
            b1.start();
            b1.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
        for(int i:b1.getNumbers()){
            System.out.println(i);
        }
        try {
            b2.start();
            b2.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
        for(int i:b2.getNumbers()){
            System.out.println(i);
        }
    }
}
 

 运行后打印信息如下:

run:
1
2
3
4
5
into this method
BubbleSortThread : java.lang.IllegalArgumentException: can't pass into a negative number at line 28 of BubbleSortThread.java
-3
-1
-5
-2
-7
成功生成(总时间:0 秒)

 

setDefaultUncaughtExceptionHandler的作用:

 

public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
 

 


设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。


上例中,当数组元素小于0时,抛出了IllegalArgumentException异常,由于线程没有设置异常处理程序,则有默认的异常处理程序捕获该异常来处理。


该方法为Thread的静态方法,设置对其他Thread对象同样有效。即其他thread发生异常但未设置异常处理程序,也会交给这个默认处理器进行异常处理。

如果一个Thread有自己的处理程序,它当然会override掉此默认的处理程序。事实上,下面是JVM在判别要如何处理一个未捕获异常时所执行的检查顺序:
1, 检查是否有此thread自有的处理程序可以调用,如果有的话,就调用它。
充:Thread的setUncaughtExceptionHandler方法:
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)设置该线程由于未捕获到异常而突然终止时调用的处理程序。
通过明确设置未捕获到的异常处理程序,线程可以完全控制它对未捕获到的异常作出响应的方式。如果没有设置这样的处理程序,则该线程的 ThreadGroup 对象将充当其处理程序。

2, 如果所属的ThreadGroup(以及它的先祖)并没有override过uncaughtException(),则对ThreadGroup层向上传递此异常,一直到遇到ThreadGroup的root为止。

充: 线程组表示一个线程的集合。此外,线程组也可以包含其他线程组。线程组构成一棵树,在树中,除了初始线程组外,每个线程组都有一个父线程组。
继承体系结构为:
java.lang
类 ThreadGroup
java.lang.Object
  ----java.lang.ThreadGroup
所有已实现的接口:
Thread.UncaughtExceptionHandler
类ThreadGroup的方法
uncaughtException(Thread t, Throwable e)
          当此线程组中的线程因为一个未捕获的异常而停止,并且线程没有安装特定 Thread.UncaughtExceptionHandler 时,由 Java Virtual Machine 调用此方法。

3, 调用Thread.getDefaultExceptionHandler()中取得的默认处理程序。



ConcurrentHashMap
该类不同步化所有的读取method。如此就立竿见影地处理掉许多锁定与threading的问题。更重要的是,ConcurrentHashMap将它内部的hashtable区段间隔开来,所以你可以在其他的thread写入到一个区段时写入到另外一个区段(除了读取是一直都被允许的)。

CopyOnWriteArrayList
该类是个thread-aware版的List,(当然)更是针对ArrayList的。这是对不常被更新但常被读取的array的最好的解决方案。它解除掉同步化,能够允许任意数目的并发读取。对于写入,它实际上创建了一个所属array的新拷贝,然后再将此新的拷贝(以及异动)分配回所属的原版的那一份。查看源代码如下:

 

//该方法没有进行同步控制
 final Object[] getArray() {
        return array;
    }
//增加元素的方法,使用了锁机制。将数组拷贝的同时,允许其他线程并发读取数组(有可能读取的数组不一样,但问题不大,可以提高读取的并发性,在设置新的数组前读取的则是旧数组,在设置后读取的是新数组)。
 public boolean add(E e) {
	final ReentrantLock lock = this.lock;
	lock.lock();
	try {
	    Object[] elements = getArray();
	    int len = elements.length;
	    Object[] newElements = Arrays.copyOf(elements, len + 1);
	    newElements[len] = e;
	    setArray(newElements);
	    return true;
	} finally {
	    lock.unlock();
	}
    }
 

 


 

打印随机数:

 

package testexecutor;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.Callable;

public class RandomPrimeSearch implements Callable{
private int bitSize;
private static final Random rng = new SecureRandom();
public RandomPrimeSearch(int bitSize){
    this.bitSize = bitSize;
}
    public BigInteger call() throws Exception {
        return BigInteger.probablePrime(bitSize, rng);
    }

}
 

 测试类:

 

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package testexecutor;

import java.math.BigInteger;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {
    public static void main(String[] args) {
        ExecutorService exe = Executors.newCachedThreadPool();
        Future<BigInteger> f1 = exe.submit(new RandomPrimeSearch(4));
        Future<BigInteger> f2 = exe.submit(new RandomPrimeSearch(3));
        exe.shutdown();//如果不加这一句,程序不会停止
        try {
            System.out.println(f1.get());
            System.out.print(f2.get());
        } catch (InterruptedException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
 

打印输出:


13
7


BigInteger的构造函数BigInteger(int numBits,Random rnd),构造一个随机生成的 BigInteger,它是在 0 到 (2的numBits次幂 - 1)(包括)范围内均匀分布的值。


无ExecutorService地执行任务
当你有一个小小的Callable对象要执行,而你又不想要ExecutorService的代价是要怎么办?可以使用FutureTask类。
java.util.concurrent.FutureTask可以被Callable对象给包起来,让他们可如同从ExecutorService.submit()所返回的Future实现般的运作。示例程序:
     

 FutureTask<BigInteger> f = new FutureTask<BigInteger>(new RandomPrimeSearch(3));
        new Thread(f).start();
        BigInteger reuslt = f.get();
 

 

查看FutureTask的javaDoc发现该类还有一个构造函数:

 

 

public FutureTask(Runnable runnable,V result)
 


创建一个 FutureTask,一旦运行就执行给定的 Runnable,并安排成功完成时 get 返回给定的结果 。
由于Runnable的run方法没有返回结果,所以在构造函数中提供参数化所指定的类型的值,它会在执行成功时有get()返回。


示例程序:


FutureTask<Object> f = new FutureTask<Object>(new MyRunnableObject(),new Integer(23));
new Thread(f).start();
System.out.println(f.get());//打印输出23





如果不需要特定的结果,则考虑使用下列形式的构造:Future<?> f = new FutureTask<Object>(runnable, null);

高等Synchronizing


Semaphore


acquire()有数种变化,可以在遇到block的时候能够对接下来要怎么做有些控制权。这包括了tryAcquire(),它要么就是没有被block住,不然就是等待指定的timeout;还有acquireUninterruptibly(),就算是遇到InterruptionException也不会罢手。


CountdownLatch


当latch的计数器减到0时,latch就会打开,而等在await()那里的thread变成没有被block并继续运行。

Exchanger


Exchanger提供了两个thread的会合点,通常用在“消费者-制造者”关系中。在某一点上这些thread必须“会合”,以交换它们个别任务的结果。
最常见的Exchanger运用方式是当生产者将数据填入缓冲区时,消费者从其他的来源将资料消耗掉。一旦生产者填满它的缓冲区,且消费者也把它自己的缓冲区消耗掉,两者就可以交换缓冲区并继续运作。然而,两方都必须在交换前完成自己的工作。Exchanger.exchange()如你所预期的就是在做这样的工作。

CyclicBarrier
一旦所有的thread都调用了await(),blocking都会被停掉,所以全部的thread就可以继续(通常是交互)。此外,barrier是全有或全无的:如果一个thread反常地失败,且提早离开barrier,则所有的thread都会反常地离开。

AtmicInteger
一个atomic类型就是有一个atomic operation可用的类型,他可以在基本上是没有block的情况下还是做到thread-safe。

        AtomicInteger ai = new AtomicInteger(0);
        int result=0;
        do{
            result = ai.get();
        }while(!ai.compareAndSet(result, result+1));
 

 

 

ReentrantLock


它是与synchronized程序区块最接近的class,即使说它有多一点的Lock功能。同时也提供了ReadWriteLock,它用来维护读取与写入分离的lock。同时可以有多个thread持有read lock,因为read通常是安全的并发操作,但只有一个thread可以持有write lock。这个class的实现(像是ReetrantReadWriteLock)用在大量的数据上是最适合的,因为读取数据发生的机会比写入一小段数据的机会大多了。

Arrays的deepToString()方法可以打印多维数组
Arrays提供的deepEquals()这个method来比较多维的array

StringBuffer的有些方法使用了同步,在你不担心有多个线程并发访问时可以使用StringBuilder类,它提供了和StringBuffer同样的功能,但没有同步。

分享到:
评论

相关推荐

    java高级复习笔记-程序阅读题.docx

    《Java高级复习笔记-程序阅读题.docx》是一份宝贵的学习资源,特别适合那些希望深入理解和掌握Java高级编程概念的学习者和开发者。以下是对这个资源的详细描述: 深度理解编程概念:这份文档提供了一系列程序阅读...

    java并发基础-课堂笔记

    该内容是在暮课网学习的课程比较,讲解进程、线程、多线程和高并发等基础知识。上传网上以供自己以后复习。

    java高级技术JUC高并发编程教程2021(1.5G)

    05-JUC高并发编程-Synchronized复习和案例分析.mp4& R: O+ [6 A8 h1 L9 | 06-JUC高并发编程-Synchronized实现案例.mp4+ ?2 `( V" U4 z3 F0 w 07-JUC高并发编程-Lock接口概述和实现案例.mp48 G J/ u; W' _$ o: {2 M ...

    [原]Java并发编程实践-读书笔记

    《Java并发编程实践》一书的个人读书笔记。主要列举包括各个章节的关键知识点,便于反复阅读和知识复习掌握。

    java并发源码-java-concurrent-test:和朱晔一起复习Java并发系列文章

    java 并发源码 源码都在test目录下。 《和朱晔一起复习Java并发》系列文章:

    Java并发专题面试总结复习总结题集

    Java并发专题面试总结复习总结题集

    高级java笔试题-Java-mianshi-note:【一线互联网大厂Java核心面试题库】Java基础、异常、集合、并发编程、JVM、Sp

    【一线互联网大厂Java核心面试题库】Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等... 2020年初开始,陆陆续续一直在收集...

    Java基础(韩顺平版)笔记详

    内容概要 韩顺平版Java基础笔记是一套详尽的Java入门教程,内容包括: Java语言概述和环境搭建 基本数据类型、变量和运算符 控制语句:条件语句和循环...面试准备:为求职者提供Java基础知识点的复习,增强面试信心。

    JAVA-2020-核心知识点整理大全.zip

    文档包含知识点较为全面,包括 java基础,集合,线程,jvm,spring,微服务,netty,各种分布式工具,设计模式,数据库,算法与数据结构,hadoop,spark等知识汇总,各部分内容表达简洁而不失重点,适合复习和检索...

    Java 复习.xmind

    数据结构,面向对象,反射,IO流,NIO,IO多路复用,JVM,并发.....

    Java领域基础部分JavaSE笔记

    Java领域基础部分aS笔记涵盖了Java编程语言的核心概念,包括但不限于: Java数据类型和变量 控制流程语句(if-else, switch, for, while等) 数组和集合 面向对象编程(OOP)基础(类,对象,继承,封装,多态) ...

    JAVA面试提纲包括JAVA基础知识总结、数据结构、JVM、多线程等

    之前前辈传下来的复习提纲,帮助校招生找到好的...其中校招真题题解,JAVA IO,JAVA 并发,JAVA 基础,JAVA容器,JVM Leetcode、LINUX,Mysql,代码风格规范,计算机操作系统、算法、剑指offer、面向对象思想、设计模式

    java复习文档,含.md程序

    不适合大学考试,适合对并发,容器等知识的复习吧!

    java7hashmap源码-learning-record:学习轨迹记录

    java7 hashmap源码 learning-record ...《Java并发编程的艺术》 8.3 控制并发线程数的Semaphore 《Java并发编程的艺术》 8.4 线程间交换数据的Exchanger 6月20号 [HashMap,LinkedHashMap,TreeMap的区别]

    2023年最新Java高并发多线程面试题

    内容概要:最新2023年Java高并发多线程后端面试题整理, 包含线程池,并发集合,volatile,CountDownLatch,Semaphore,Phaser,AQS,ReentrantLock,ReentrantLock等等问题, 用简洁明了的语言,通俗易懂地阐述了高...

    java面试复习题.zip

    【一线互联网大厂Java核心面试题库】Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等..

    互联网Java面试训练营.rar

    Java 1. 面试现场】为什么MySQL数据库要用B+树存储索引? 2. 【漫画】以后在有面试官...14. 2020年大厂Java面试前复习的正确姿势(800+面试题附答案解析) 15. 大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?

    Java并发程序设计教程

    内容列表 1、使用线程的经验:设置名称、响应中断、使用ThreadLocal 2、Executor :ExecutorService和Future ☆☆☆ 3、阻塞队列: put和take、offer和poll、drainTo 4、线程间的协调手段:lock、condition...12、复习题

    java8stream源码-java8-learning:通过复习OCA和OCP来学习Java8

    java8流源码Java8学习 准备 目录 高级班级设计 设计模式和原则 泛型和集合 函数式编程 日期、字符串和本地化 异常和断言 并发 输入输出 蔚来2 JDBC

    阿里Java并发程序设计教程

    1、使用线程的经验:设置名称、响应中断、使用ThreadLocal 2、Executor :ExecutorService和Future ☆ ☆ ☆ 3、阻塞队列 : put和take、offer和poll、drainTo 4、线程间的协调手段:lock、condition、wait...12、复习题

Global site tag (gtag.js) - Google Analytics