chapter 20 注解

三种标准注解和四种元注解:

编写注解处理器

chapter 21 并发

基本的线程机制

定义任务

package cn.test;

public class LiftOff implements Runnable {
protected int countDown = 10;
private static int taskCount=0;
private final int id= taskCount++;
public LiftOff() {}
public LiftOff(int countDown) {
this.countDown=countDown;
}
public String status() {
return "#"+id+"("+
(countDown > 0 ? countDown:"Liftoff!")+"),";
}
@Override
public void run() {
while(countDown-->0) {
System.out.print(status());
Thread.yield();//线程重新抢占
}
}
}

public class MainThread {
  public static void main(String[] args) {
    LiftOff launch=new LiftOff();
    launch.run();
  }
}

Thread类

public class BasicThreads {
public static void main(String[] args) {
for(int i=0;i<5;i++) {
new Thread(new LiftOff()).start();
}
System.out.println("Waiting for LiftOff");
}
}

使用Executor

public class CachedThreadPool {
public static void main(String[] args) {
// ExecutorService exec=Executors.newCachedThreadPool();
ExecutorService exec=Executors.newFixedThreadPool(5);
// ExecutorService exec=Executors.newSingleThreadExecutor();
for(int i=0;i<5;i++) {
exec.execute(new LiftOff());
}
exec.shutdown();
}
}

从任务中产生返回值

  Runnable 不会返回任何值。使用Callable接口能够返回一个值。

package cn.test;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id=id;
}
@Override
public String call() throws Exception {
return "result of TaskWithResult "+ id;
}
}
public class CallableDemo{
public static void main(String[] args) {
ExecutorService exec=Executors.newCachedThreadPool();
ArrayList<Future<String>> results=new ArrayList<Future<String>>();
for(int i=0;i<10;i++) {
results.add(exec.submit(new TaskWithResult(i)));
}
for(Future<String> fs:results) {
try {
System.out.println(fs.get());
} catch (InterruptedException e) {
System.out.println(e);
return;
} catch (ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
}

休眠

  Thread.sleep();

优先级

package cn.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class SimplePriorities implements Runnable{
private int countDown=5;
private volatile double d;
private int priority;
public SimplePriorities(int priority) {
this.priority=priority;
}
public String toString() {
return Thread.currentThread()+":"+countDown;
}
@Override
public void run() {
Thread.currentThread().setPriority(priority);
while(true) {
for(int i=1;i<100000;i++) {
d+=(Math.PI+Math.E)/(double)i;
if(i%1000 == 0)
Thread.yield();
}
System.out.println(this);
if(--countDown == 0) return;
}
}
public static void main(String[] args) {
ExecutorService exec=Executors.newCachedThreadPool();
for(int i=0;i<5;i++)
exec.execute(new SimplePriorities(Thread.MIN_PRIORITY));
exec.execute(new SimplePriorities(Thread.MAX_PRIORITY));
exec.shutdown();
} }

让步

  Thread.yield();

后台线程

  daemon线程。

package cn.test;

public class SimpleDaemons implements Runnable{
public void run() {
try {
while(true) {
Thread.sleep(100);
System.out.println(Thread.currentThread()+" "+this);
}
} catch (Exception e) {
System.out.println("sleep() interrupted");
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
for(int i=0;i<10;i++) {
Thread daemon=new Thread(new SimpleDaemons());
daemon.setDaemon(true);
daemon.start();
}
System.out.println("All daemons started");
Thread.sleep(100);
} }

使用isDaemon()方法来确定线程是否是一个后台线程。

package cn.test;

import java.util.concurrent.TimeUnit;

class Daemon implements Runnable{
private Thread[] t=new Thread[10];
public void run() {
for(int i=0;i<t.length;i++) {
t[i]=new Thread(new DaemonSpawn());
t[i].start();
System.out.println("DaemonSpawn "+i+" started,");
}
for(int i=0;i<t.length;i++)
System.out.println("t["+i+"].siDaemon()="+
t[i].isDaemon()+",");
while(true) {
Thread.yield();
}
}
class DaemonSpawn implements Runnable{
public void run() {
while(true)
Thread.yield();
}
}
}
public class Daemons {
public static void main(String[] args) throws InterruptedException {
Thread d=new Thread(new Daemon());
d.setDaemon(true);
d.start();
System.out.println("d.isDaemon()="+d.isDaemon()+",");
TimeUnit.SECONDS.sleep(1); }
}

一旦main()退出,JVM就会立即关闭所有的后台进程。

package cn.test;

import java.util.concurrent.TimeUnit;

class ADaemon implements Runnable{
public void run() {
try {
System.out.println("Starting ADaemon");
TimeUnit.SECONDS.sleep(1);
}catch(Exception e) {
System.out.println("Exiting via InterruptedException");
}finally {
System.out.println("This should always run?");
}
}
}
public class DaemonsDontRunFinally {
public static void main(String[] args) throws Exception {
Thread t= new Thread(new ADaemon());
t.setDaemon(true);
t.start();
// TimeUnit.SECONDS.sleep(1);
}
}

编码的变体

package cn.test;

import java.util.concurrent.TimeUnit;

class ADaemon implements Runnable{
public void run() {
try {
System.out.println("Starting ADaemon");
TimeUnit.SECONDS.sleep(1);
}catch(Exception e) {
System.out.println("Exiting via InterruptedException");
}finally {
System.out.println("This should always run?");
}
}
}
public class DaemonsDontRunFinally {
public static void main(String[] args) throws Exception {
Thread t= new Thread(new ADaemon());
t.setDaemon(true);
t.start();
// TimeUnit.SECONDS.sleep(1);
}
}

加入一个线程【】

package cn.test;
class Sleeper extends Thread{
private int duration;
public Sleeper(String name,int sleepTime) {
super(name);
duration=sleepTime;
start();
}
public void run() {
try {
sleep(duration);
} catch(InterruptedException e) {
System.out.println(getName()+" was interrupted ."+
"isInterrupted():"+isInterrupted());
return;
}
System.out.println(getName()+" has awakened");
}
}
class Joiner extends Thread{
private Sleeper sleeper;
public Joiner(String name,Sleeper sleeper) {
super(name);
this.sleeper=sleeper;
start();
}
public void run() {
try {
sleeper.join();
}catch (InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println(getName()+" join completed");
}
}
public class Joining {
public static void main(String[] args) {
Sleeper
sleepy=new Sleeper("Sleeper",1500),
grumpy=new Sleeper("Grumpy",1500);
Joiner
dopey=new Joiner("Dopey",sleepy),
doc=new Joiner("Doc",grumpy);
grumpy.interrupt();
}
}

创建有响应的用户界面

  使用线程的动机之一就是建立有响应的用户界面。

package cn.test;

import java.io.IOException;

class UnresponsiveUI{
private volatile double d=1;
public UnresponsiveUI() throws IOException {
while(d>0)
d=d+(Math.PI+Math.E)/d;
System.in.read();
}
}
public class ResponsiveUI extends Thread{
private static volatile double d=1;
public ResponsiveUI() {
setDaemon(true);
start();
}
@Override
public void run() {
while(true)
d=d+(Math.PI+Math.E)/d;
}
public static void main(String[] args) throws IOException {
// new UnresponsiveUI();
new ResponsiveUI();
System.in.read();
System.out.println(d);
}
}

  

线程组

捕获异常

  

package cn.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ExceptionThread implements Runnable{
public void run() {
throw new RuntimeException();
}
public static void main(String[] args) {
try {
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ExceptionThread());
}catch(RuntimeException ue) {  //无法捕获异常
System.out.println("Exception has been handled!");
}
}
}
package cn.test;

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

package cn.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class SettingDefaultHandler {
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(
new MyUncaughtExceptionHandler());
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ExceptionThread());
}
}

共享受限资源

不正确地访问资源

package cn.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; abstract class IntGenerator{
private volatile boolean canceled=false;
public abstract int next();
public void cancel() {canceled=true;}
public boolean isCanceled() {return canceled;}
}
public class EvenChecker implements Runnable{
private IntGenerator generator;
private final int id;
public EvenChecker (IntGenerator g,int ident) {
generator = g;
id = ident;
}
public void run() {
while(!generator.isCanceled()) {
int val=generator.next();
if(val%2!=0) {
System.out.println(val+" not even!");
generator.cancel();
}
}
}
public static void test(IntGenerator gp,int count) {
System.out.println("Press Control-C to exit");
ExecutorService exec=Executors.newCachedThreadPool();
for(int i=0;i<count;i++)
exec.execute(new EvenChecker(gp,i));
exec.shutdown();
}
public static void test(IntGenerator gp) {
test(gp,10);
}
} package cn.test; public class EvenGenerator extends IntGenerator {
private int currentEvenValue=0;
public int next() {
++currentEvenValue;
++currentEvenValue;
return currentEvenValue;
}
public static void main(String[] args) {
EvenChecker.test(new EvenGenerator());
}
}

在java中,递增不是原子性的操作。因此,如果不保护任务,即使单一的递增也是不安全的。

解决共享资源竞争

  序列化访问共享资源方法。

  互斥量。

(该类的其他对象调用synchronized任务的操作被锁定,只有已经进入被锁任务的那个对象完成任务后才可竞权)

package cn.test;

public class EvenGenerator extends IntGenerator {
private int currentEvenValue=0;
public synchronized int next() {
++currentEvenValue;
Thread.yield();
++currentEvenValue;
return currentEvenValue;
}
public static void main(String[] args) {
EvenChecker.test(new EvenGenerator());
}
}

使用显式的Lock对象

java.util.concurrent.locks

package cn.test;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MutexEvenGenerator extends IntGenerator{
private int currentEvenValue=0;
private Lock lock=new ReentrantLock();
public int next() {
lock.lock();
try {
++currentEvenValue;
Thread.yield();
++currentEvenValue;
return currentEvenValue;
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
EvenChecker.test(new MutexEvenGenerator());
} }
package cn.test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; public class AttemptLocking {
private ReentrantLock lock=new ReentrantLock();
public void untimed() {
boolean captured=lock.tryLock();
try {
System.out.println("untimed tryLock(): "+captured);
}finally {
if(captured)
lock.unlock();
}
}
public void timed() {
boolean captured = false;
try {
captured = lock.tryLock(2, TimeUnit.SECONDS);
}catch(InterruptedException e) {
throw new RuntimeException(e);
}
try {
System.out.println("timed tryLock(2,TimeUnit.SECONDS): "
+captured);
}finally {
if(captured)
lock.unlock();
}
}
public static void main(String[] args) {
final AttemptLocking al=new AttemptLocking();
al.untimed();
al.timed();
new Thread() {
{setDaemon(true);}
public void run() {
al.lock.lock();
System.out.println("acquired");
}
}.start();
Thread.yield();
al.untimed();
al.timed();
}
}

原子性与易变性

理解volatile

java中,对域中的值做赋值和返回操作是原子性的。

package cn.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class AtomicityTest implements Runnable{
private int i=0;
public int getValue() {return i;}
private synchronized void evenIncrement() {i++;i++;}
public void run() {
while(true)
evenIncrement();
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest();
exec.execute(at);
while(true) {
int val=at.getValue();
if(val % 2 != 0) {
System.out.println(val);
System.exit(0);
}
}
}
}

原子类

package cn.test;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerTest implements Runnable{
private AtomicInteger i=new AtomicInteger(0);
public int getValue() {return i.get();}
private void evenIncrement() {i.addAndGet(2);}
public void run() {
while(true)
evenIncrement();
}
public static void main(String[] args) {
new Timer().schedule(new TimerTask() {
public void run() {
System.err.println("Aborting");
System.exit(0);
}
}, 5000);
ExecutorService exec=Executors.newCachedThreadPool();
AtomicIntegerTest ait=new AtomicIntegerTest();
exec.execute(ait);
while(true) {
int val=ait.getValue();
if(val % 2 != 0) {
System.out.println(val);
System.exit(0);
}
}
} }

临界区(同步控制块)【】

在其他对象上同步

package cn.test;
class DualSynch{
private Object syncObject = new Object();
public synchronized void f() {
for(int i=0;i<5;i++) {
System.out.println("f()");
Thread.yield();
}
}
public void g() {
synchronized(syncObject) {
for(int i=0;i<5;i++) {
System.out.println("g()");
Thread.yield();
}
}
}
}
public class SyncObject {
public static void main(String[] args) {
final DualSynch ds=new DualSynch();
new Thread() {
public void run() {
ds.f();
}
}.start();
ds.g();
}
}

线程本地存储【】

package cn.test;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; class Accessor implements Runnable{
private final int id;
public Accessor (int idn) {id=idn;}
public void run() {
while(!Thread.currentThread().isInterrupted()) {
ThreadLocalVariableHolder.increment();
System.out.println(this);
Thread.yield();
}
}
public String toString() {
return "#"+id+": "+ThreadLocalVariableHolder.get();
}
}
public class ThreadLocalVariableHolder {
private static ThreadLocal<Integer> value=
new ThreadLocal<Integer>() {
private Random rand=new Random(47);
protected synchronized Integer initialValue() {
return rand.nextInt(10000);
}
};
public static void increment() {
value.set(value.get()+1);
}
public static int get() {return value.get();}
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i=0;i<5;i++)
exec.execute(new Accessor(i));
TimeUnit.SECONDS.sleep(3);
exec.shutdown();
}
}
package cn.test;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; class Accessor implements Runnable{
private final int id;
public Accessor (int idn) {id=idn;}
public void run() {
while(!Thread.currentThread().isInterrupted()) {
ThreadLocalVariableHolder.increment();
System.out.println(this);
Thread.yield();
}
}
public String toString() {
return "#"+id+": "+ThreadLocalVariableHolder.get();
}
}
public class ThreadLocalVariableHolder {
private static ThreadLocal<Integer> value=
new ThreadLocal<Integer>() {
private Random rand=new Random(47);
protected synchronized Integer initialValue() {
return rand.nextInt(10000);
}
};
public static void increment() {
value.set(value.get()+1);
}
public static int get() {return value.get();}
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i=0;i<5;i++)
exec.execute(new Accessor(i));
TimeUnit.SECONDS.sleep(3);
exec.shutdown();
}
}

终结任务

装饰性花园

package cn.test;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; class Count{
private int count=0;
private Random rand=new Random(47);
public synchronized int increment() {
int temp=count;
if(rand.nextBoolean())
Thread.yield();
return (count= ++temp);
}
public synchronized int value() {return count;}
}
class Entrance implements Runnable{
private static Count count=new Count();
private static List<Entrance> entrances=
new ArrayList<Entrance>();
private int number=0;
private final int id;
private static volatile boolean canceled=false;
public static void cancel() {canceled =true;}
public Entrance(int id) {
this.id=id;
entrances.add(this);
}
public void run() {
while(!canceled) {
synchronized(this) {
++number;
}
System.out.println(this+"Total: "+count.increment());
try {
TimeUnit.MICROSECONDS.sleep(100);
}catch(InterruptedException e) {
System.out.println("sleep interrupted");
}
}
System.out.println("Stopping "+this);
}
public synchronized int getValue() {return number;}
public String toString() {
return "Entrance "+id+": "+getValue();
}
public static int getTotalCount() {
return count.value();
}
public static int sumEntrances() {
int sum=0;
for(Entrance entrance:entrances)
sum+=entrance.getValue();
return sum;
}
}
public class OrnamentalGarden {
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i=0;i<5;i++)
exec.execute(new Entrance(i));
TimeUnit.SECONDS.sleep(3);
Entrance.cancel();
exec.shutdown();
if(!exec.awaitTermination(250, TimeUnit.MICROSECONDS))
System.out.println("Some tasks were not terminated!");
System.out.println("Total: "+Entrance.getTotalCount());
System.out.println("Sum of Entrances: "+Entrance.sumEntrances());
}
}

在阻塞时终结

线程状态:

  1. 新建
  2. 就绪
  3. 阻塞
  4. 死亡

进入阻塞状态

  调用sleep(milliseconds)会进入休眠状态,设定的时间结束时继续运行。

  调用wait()使线程挂起,直到线程被notify()或notifyAll(),线程会进入就绪状态。

  当前任务的等待输入/输出。

  当然任务被阻塞在锁外。

中断

  cancel()是一种中断由Executor启动的单个线程的方式。

package cn.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; class SleepBlocked implements Runnable{
public void run() {
try {
TimeUnit.SECONDS.sleep(100);
} catch(InterruptedException e) {
System.out.println("InterruptedException");
}
System.out.println("Exiting SleepBlocked.run() ");
}
}
class IOBlocked implements Runnable{
private InputStream in;
public IOBlocked(InputStream in) {this.in = in; }
public void run() {
try {
System.out.println("Waiting for read():");
in.read();
} catch (IOException e) {
if(Thread.currentThread().isInterrupted())
System.out.println("Interrupted from blocked I/O");
else
throw new RuntimeException();
}
System.out.println("Exiting IOBlocked.run() ");
} }
class SynchronizedBlocked implements Runnable{
public synchronized void f() {
while(true)
Thread.yield();
}
public SynchronizedBlocked() {
new Thread() {
public void run() {
f();
}
}.start();
}
public void run() {
System.out.println("Trying to call f()");
f();
System.out.println("Exiting SynchronizedBlocked.run()");
}
}
public class Interrupting {
private static ExecutorService exec=
Executors.newCachedThreadPool();
static void test(Runnable r) throws InterruptedException {
Future<?> f= exec.submit(r);
TimeUnit.MICROSECONDS.sleep(100);
System.out.println("Interrupting "+r.getClass().getName());
f.cancel(true);
System.out.println("Interrupt sent to "+r.getClass().getName());
}
public static void main(String[] args) throws Exception {
test(new SleepBlocked());
test(new IOBlocked(System.in));
test(new SynchronizedBlocked());
TimeUnit.SECONDS.sleep(3);
System.out.println("Aborting with System.exit(0)");
System.exit(0);
}
}

被互斥所阻塞【】

package cn.test;

public class MultiLock {
public synchronized void f1(int count) {
if(count-- >0) {
System.out.println("f1() calling f2() with count "+count);
f2(count);
}
}
public synchronized void f2(int count) {
if(count-- >0) {
System.out.println("f2() calling f1() with count "+count);
f1(count);
}
}
public static void main(String[] args) {
final MultiLock multiLock=new MultiLock();
new Thread() {
public void run() {
multiLock.f1(10);
}
}.start();
}
}
package cn.test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; class BlockedMutex{
private Lock lock=new ReentrantLock();
public BlockedMutex() {
lock.lock();
}
public void f() {
try {
lock.lockInterruptibly();
System.out.println("lock acquired in f()");
} catch (InterruptedException e) {
System.out.println("Interrupted from lock acquisition in f()");
}
}
}
class Blocked2 implements Runnable {
BlockedMutex blocked=new BlockedMutex();
public void run() {
System.out.println("Waiting for f() in BlockedMutex");
blocked.f();
System.out.println("Broken out of blocked call");
}
}
public class Interrupting2 {
public static void main(String[] args) throws Exception {
Thread t= new Thread(new Blocked2());
t.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("Issuing t.interrupt()");
t.interrupt();
}
}

检查中断

线程之间的协作

wait()与notifyAll()

package cn.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; class Car{
private boolean waxOn=false;
public synchronized void waxed() {
waxOn=true;
notifyAll();
}
public synchronized void buffed() {
waxOn=false;
notifyAll();
}
public synchronized void waitForWaxing() throws InterruptedException {
while(waxOn== false)
wait();
}
public synchronized void waitForBuffing() throws InterruptedException {
while(waxOn== true)
wait();
}
}
class WaxOn implements Runnable{
private Car car;
public WaxOn(Car c) {car= c;}
public void run() {
try {
while(!Thread.interrupted()) {
System.out.println("Wax On!");
TimeUnit.MILLISECONDS.sleep(200);
car.waxed();
car.waitForBuffing();
}
}catch(InterruptedException e) {
System.out.println("Exiting via interrupt");
}
System.out.println("Ending Wax On task");
}
}
class WaxOff implements Runnable{
private Car car;
public WaxOff(Car c) {car=c;}
public void run() {
try {
while(!Thread.interrupted()) {
car.waitForWaxing();
System.out.println("Wax Off!");
TimeUnit.MILLISECONDS.sleep(200);
car.buffed();
}
}catch(InterruptedException e) {
System.out.println("Exiting via interrupt");
}
System.out.println("Ending Wax Off task");
}
}
public class WaxOMatic {
public static void main(String[] args) throws Exception {
Car car=new Car();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new WaxOff(car));
exec.execute(new WaxOn(car));
TimeUnit.SECONDS.sleep(5);
exec.shutdownNow();
}
}

  

《Think in Java》20 21(并发)的更多相关文章

  1. 深入浅出 Java Concurrency (21): 并发容器 part 6 可阻塞的BlockingQueue (1)[转]

    在<并发容器 part 4 并发队列与Queue简介>节中的类图中可以看到,对于Queue来说,BlockingQueue是主要的线程安全版本.这是一个可阻塞的版本,也就是允许添加/删除元 ...

  2. JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  3. [转] JAVA多线程和并发基础面试问答

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  4. JAVA多线程和并发基础面试问答

    转载: JAVA多线程和并发基础面试问答 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对 ...

  5. 【多线程】JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  6. (转)JAVA多线程和并发基础面试问答

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  7. JAVA多线程和并发基础面试问答【转】

    JAVA多线程和并发基础面试问答 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰 ...

  8. 17、JAVA多线程和并发基础面试问答

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  9. to meet you Java多线程与并发

    2: hotspot中对象在内存的布局是分3部分 对象头 实例数据 对其填充 这里主要讲对象头:一般而言synchronized使用的锁对象是存储在对象头里的,对象头是由Mark Word和Class ...

随机推荐

  1. Shell32.ShellClass服务器操作系统无法获取 音频文件时长问题

    前言: 上传音频文件,自动写入此音频文件的时长,这里用 COM组件Microsoft Shell Controls And Automation来实现. 首先 1.引用:Microsoft Shell ...

  2. iOS开发基础控件--UITextField

    001 //初始化textfield并设置位置及大小 002   UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20 ...

  3. bootstrap-select.js 下拉框多选后动态赋值

    话不多说先上demo 其实demo是从官网下载的 只稍作改动 由于没有搞清楚怎么上传源代码 就把官网的链接贴出来吧 https://github.com/silviomoreto/bootstrap- ...

  4. spring与IOC,ioc与di的关系

  5. Linux实战教学笔记32:企业级Memcached服务应用实践

    一, Memcached介绍 1.1 Memcached与常见同类软件对比 (1)Memcached是什么? Memcached是一个开源的,支持高性能,高并发的分布式内存缓存系统,由C语言编写,总共 ...

  6. UIPanel

    [UIPanel] UIPanel is a component that collects and manages all widgets underneath it. UIPanel is res ...

  7. Python 2.7 爬取51job 全国java岗位

      一页有50条数据一共2000页 分页是get分页 #!/usr/bin/python # encoding: utf-8 import requests import threading from ...

  8. css的优先级和权重问题 以及!important优先级

    一,前言: 刚加的css怎么没有渲染出来?浏览器中查看,发现是被其他的css给覆盖了,相信我们都曾遇到过这样的问题.那么浏览器是如何选择css标签的渲染顺序的呢?换句话说,css选择器的优先级是怎么规 ...

  9. HoloLens的显示分辨率有多少?

    作者:胡痴儿2.0链接:https://www.zhihu.com/question/27737626/answer/92339648来源:知乎著作权归作者所有,转载请联系作者获得授权. 左右眼各,7 ...

  10. hadoop组件启动和关闭命令

    一.启动相关组件之前 一般安装完hadoop之后需要格式化一遍hdfs: hdfs namenode -format 然后再进行其他组件的启动,hadoop相关组件都是用位于...hadoop/sbi ...