分类 Java 相关 下的文章

Java Collection Framework List, Set, Queue, Deque 关系图

使用 https://www.draw.io/ 在线画的, 只涉及到List, Set, Queue, Deque. 只包含util 包里面的类和接口.
接口以圆角长方形表示, 类以直角长方形表示.

在线浏览版本: https://drive.google.com/file/d/0B6ry0l2WQQIjclhSSGZyNGgxX1k/view?usp=sharing

离线下载版本, 下面 png 格式图片, 可以另存为, 放大. 也可以下载pdf 格式
pdf version: JavaCollection.pdf
JavaCollection.png

tomcat 配置在linux上, 机器重启后 自动启动

#!/bin/bash

### BEGIN INIT INFO
# Provides:        tomcat7
# Required-Start:  $network
# Required-Stop:   $network
# Default-Start:   2 3 4 5
# Default-Stop:    0 1 6
# Short-Description: Start/Stop Tomcat server
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin

start() {
 sh /opt/apache-tomcat-7.0.59/bin/startup.sh
}

stop() {
 sh /opt/apache-tomcat-7.0.59/bin/shutdown.sh
}

case $1 in
  start|stop) $1;;
  restart) stop; start;;
  *) echo "Run as $0 <start|stop|restart>"; exit 1;;
esac

chmod 755 /etc/init.d/tomcat7
update-rc.d tomcat7 defaults

另外一种写法

 #!/bin/sh
 #tomcat auto-start
 case $1 in
        start)
            sh /opt/apache-tomcat-7.0.59/bin/startup.sh;;
        stop)
            sh /opt/apache-tomcat-7.0.59/bin/shutdown.sh;;
        restart)
            sh /opt/apache-tomcat-7.0.59/bin/shutdown.sh
            sh /opt/apache-tomcat-7.0.59/bin/startup.sh;;
        *)
            echo 'Usage:tomcat7 start|stop|restart';;
    esac
    exit 0

从这里抄过来的: http://askubuntu.com/questions/223944/how-to-automatically-restart-tomcat7-on-system-reboots

Java Executor Framework

Executor Framework

Executor framework 以Executor接口为核心, 有ExecutorService 和 ScheduledExecutorService 2 个子接口, 提供了线程创建, 销毁的快捷方式, 并且线程可以做到复用.

Runnable VS Callable

  1. Callable 提供的call() 方法, 可以异步返回结果, 可以throw checked Exception;
  2. ExecutorService 接口可以通过 submit, invokeAny, invokeAll 去执行Callable 接口, 返回Future.

ExecutorService

shutdown() 和 shutdownNow() 的区别在于是否执行pending的task.
如果当前线程要等待ExecutorService的线程都执行完, 必须调用shutdown / shutdownNow, 然后调用
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException.
invokeAny() 方法返回最快的一个Task 结果, 如果第一个有Exception, 一次找后面比较快的, 如果都有异常, 则返回异常.

Future

ExecutorService 的 submit(), invokeAll(), invokeAny() 都返回Future对象, 它能track Callable 执行的状态, 能cancel Callable.

FutureTask

FutureTask 实现了Runnable, Future, RunnableFuture 接口.
因为实现了Runnable接口, 所以可以被Thread, ExecutorService执行.
因为实现了Future 接口, 所以可以track status, 可以被cancel;
构造函数可以封装 Runnable 和 Callable.

一张图总结一下:
box-598143524220884.jpg

线程同步工具类[2]

Phaser

适用于分阶段的线程同步. 可以在构造时设置一个初始的参与的线程个数, 也可以后边通过方法注册与注销. 所以它的生命周期内参与的线程数是可以变化的. 当其中参与的线程到达某个phase的确认点之后, 可以选择等待,或直接继续, 或者不参与到下一个phase.
Phaser内部维护phase的数值, 记录当前那些phase到达的数量, 但是不会维护参与者的信息. 这里有个很重要的概念是: Phase 并不管有多少线程, 它只管每个阶段达到方法被调用的次数, 只要被调用的次数足够, 它就到下一阶段, 典型的是Phaser的注册数有N个, 但是这N全是一个线程在调用arrive() 方法. 当然如果是要求多个同步, 一般是多个线程调用arriveAndAwaitAdvance(). 这个phase 数值从0 开始, 当要求的参与者都到达之后加一.

public int arrive() 方法不会等待其他参与者, 当此线程下次调用相关的arrive*()方法的时候, 有可能还是当前phase, 是当前phase的到达者加一. 如
public static void main(String[] args) {
Phaser p = new Phaser(3);

    System.out.println(p.arrive());
    System.out.println(p.arrive());
    System.out.println(p.arrive());
    
    System.out.println(p.arrive());
    System.out.println(p.arrive());
    System.out.println(p.arrive());
    p.forceTermination();
}

public int arriveAndAwaitAdvance() 方法等同于awaitAdvance(arrive()), 和 CyclicBarrier的await() 方法类似.

不等待: arrive();
不等待并且使参与者减少一个: arriveAndDeregister()
等待这一个phase结束并且使参与者减少一个: awaitAdvance(arriveAndDeregister())

public int awaitAdvance(int phase) 这个方法很容易让人迷糊, 以为它会一直等待第N phase, 其实不然, 只要是当前phase 和N 不相等, 就立马返回. 所以, 如果你想真正的等待第N phase, 那么你可能需要这么做:
while (p.getPhase() < N) {
p.awaitAdvance(p.getPhase()); // 前提是你N之前都没注册
}
//此处已到N或者N+

protected boolean onAdvance(int phase, int registeredParties) 方法是在所有参与者到达后, 下一phase 开始之前执行的, 类似CyclicBarrier 的Action Command. 这个方法可以用来override 去替换一些特定的Action. 如果返回值是true, 则本phase 是最后一个阶段.
如果Phaser 已经终止, 则后面的await都会立马返回.

Exchanger

在一个同步点, 2个线程彼此通过Exchanger交换数据.

线程同步工具类[1]

Low level synchronize

Java 提供的Low level 同步方式主要有 synchronize 关键字 和 Lock 的实现类.
Lock的实现类主要有 ReentrantLock 和 ReentrantReadWriteLock.ReadLock 和 ReentrantReadWriteLock.WriteLock;
使用Object的wait(), notify() 和notifyAll() 方法, 也可以实现同步.

High level synchronize

Java 提供的high level 同步方式主要有
Semaphore, CountDownLatch, CyclicBarrier, Phaser, Exchanger.

Semaphore

Semaphore一般用来对共享资源的限制访问, 通过构造函数参数设置共享资源的总量, 通过acquire() 获得访问权限, 通过release() 释放已经获得的权限.
通过设置fair参数, 可以设置是否可以公平获得.
当acquire() 不能立即得到时, 当前线程会挂起, 直到获得或者被interrupted . acquire()的变种有:
void acquire(int permits);
void acquireUninterruptibly();
void acquireUninterruptibly(int permits);
boolean tryAcquire();
boolean tryAcquire(int permits);
boolean tryAcquire(int permits, long timeout, TimeUnit unit);
boolean tryAcquire(long timeout, TimeUnit unit);
release() 方法也有变种 release(int), 一次release 多个permit.
当permit 只有1的时候, 通常被称之为Binary Semaphore, 与很多Lock机制类似.
还提供了一些其他实用方法去check semaphore的当前状态, 比如: availablePermits(), getQueuedThreads(), getQueueLength(), isFair().

CountDownLatch

CountDownLatch 是一个非常简洁的线程同步实用工具, 初始设置等待的事件数为N (构造函数设置), 在等待的线程通过await()方法被block住, 直到有足够的其它线程调用Latch的countDown() 方法, 一直到count down 到0.
并不需要有N个线程调用countDown() 方法, 也许更多, 也许更少, 一个线程调用countDown方法之后, 不会被block, 会继续运行(与CyclicBarrier不同), 它有可能多次调用countDown() 方法.
同时, 也不一定只有一个线程在await(), 可能有多个线程同时在等待.
await() 的另外一个变种是只wait固定的时间await(long timeout, TimeUnit unit);
count数不能reset, 只能在构造函数时传入, 一旦count down 到0, 后续的await() 线程return immediately, 不会被block.

CyclicBarrier

N个线程等待一个同步点. 每个线程在同步点的代码处调用await()方法, 同时被block住, 直到有N个线程都调用了await()方法, 则所有在此同步点被block的线程被release. 被release之后, 这个Barrier可以被重复利用, 只要调用reset()方法, 就可以再次被利用, 所以冠以 Cyclic.
CyclicBarrier可选设置一个Runnable Command, 当N个线程都达到同步点之后, 并且在这些线程被release 之前, 这个Runnable command 被执行, 可以做一些求和, 总结之类的事情.
await() 有个变种, 可以设置最长等待时间 public int await(long timeout, TimeUnit unit);
await() 的返回值是线程到达barrier的index, (parties -1) 是第一个, 0 代表最后一个. 如果设置了Runnable Command, 那么最后一个到达的去执行这个Runnable Command. 如果你想设置第一个到达的去执行, 可以不要设置到 CyclicBarrier的构造函数中, 而是判断 await() 方法的返回值(arrival index).
若任何等待线程在等待期间被interrupt, 则所有线程抛出 InterruptedException;
若Barrier 被reset, 则抛出 BrokenBarrierException.
若设置的 timeout 时间超时, 则抛出 TimeoutException.
如果有线程timeout 或者被 interrupt, 或者Barrier Action 发生异常, 都会导致Barrier 变成 Broken 状态.