Thinking In Java 之 多线程 1
来源:互联网 发布:大数据技术论文 编辑:程序博客网 时间:2024/06/04 22:17
Thinking In Java 之多线程
Using Executors
- The call to shutdown() prevents new task from being submitted to that Executor.
- Note that in any of the thread pools, existing threads are automatically reused when possible.
- A SingleThreadExecutor serializes the tasks that are submitted to it, and maintain its own (hidden) queue of pending task. SingleThreadExecutor to ensure that only one task at a time is running from any thread. This way, you don’t need to deal with synchronizing on the shared resource (and you won’t clobber the file system in the meantime).
Producing return values form tasks
class TaskWithResult implements Callable<String> { private int id; public TaskWithResult(int id) { this.id = id; } public String call() { 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 { // get() blocks until completion: System.out.println(fs.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } finally { exec.shutdown(); } } }}
The overloaded Executors.callable() method tasks a Runnable and produces a Callable.
Sleeping
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.println(status()); // I've done the important parts of my cycle and this would be a good // time to switch to another task for a while. Thread.yield(); } }}
public class SleepingTask extends LiftOff{ public void run() { try { while(countDown-- > 0) { System.out.print(status()); TimeUnit.MILLISECONDS.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); for(int i=0;i<5;i++) { exec.execute(new SleepingTask()); } exec.shutdown(); }}
Because exceptions won’t propagate across threads back to main(), you must locally handle any exceptions that arise within a task.
Priority
Lower-priority threads just tend to run less often.
public class SimplePrioroties implements Runnable{ private int countDown = 5; private volatile double d;// No optimization private int priority; public SimplePrioroties(int priority) { this.priority = priority; } public String toString() { return Thread.currentThread() + ": " + countDown; } @Override public void run() { Thread.currentThread().setPriority(priority);//! while(true) { // An expensive, interruptable operation: for(int i=1;i<10000;i++) { d += (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 SimplePrioroties(Thread.MIN_PRIORITY)); } exec.execute(new SimplePrioroties(Thread.MAX_PRIORITY)); exec.shutdown(); }}
You can get a reference to the Thread object that is driving a task, inside that task, by calling Thread.currentThread().
Note that the priority is set at the beginning of run(); setting it in the constructor would do no good since the Executor has not begun the task at that point.
Daemon thread
public class SimpleDaemon implements Runnable{ @Override public void run() { try { while(true) { TimeUnit.MILLISECONDS.sleep(100); System.out.println(Thread.currentThread() + " " + this); } } catch (InterruptedException e) { System.out.println("sleep() interrupted"); } } public static void main(String[] args) throws InterruptedException { for(int i=0;i<10;i++) { Thread daemon = new Thread(new SimpleDaemon()); daemon.setDaemon(true); daemon.start(); } System.out.println("All daemon started"); TimeUnit.MILLISECONDS.sleep(175); }}
When all of the non-daemon threads complete, the program is terminated, killing all daemon threads in the process.
以下例子使用到了ThreadFactory,可与上面的例子做对比。
public class DaemonThreadFactory implements ThreadFactory{ @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setDaemon(true); return t; }}
public class DaemonFromFactory implements Runnable{ @Override public void run() { try { while(true) { TimeUnit.MILLISECONDS.sleep(100); System.out.println(Thread.currentThread() + " " + this); } } catch (InterruptedException e) { System.out.println("Interrupted"); } } public static void main(String[] args) throws InterruptedException { ExecutorService exec = Executors.newCachedThreadPool(new DaemonThreadFactory()); for(int i=0;i<10;i++) { exec.execute(new DaemonFromFactory()); } System.out.println("All daemons started"); TimeUnit.MILLISECONDS.sleep(500); }}
——————————
public class DaemonsDontRunFinally { public static void main(String[] args) { Thread t = new Thread(new ADaemon()); t.setDaemon(true); t.start(); }}class ADaemon implements Runnable{ @Override public void run() { try { System.out.println("Starting ADaemon"); TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { System.out.println("Exiting via InterruptedException"); }finally { System.out.println(); } }}
When you run this program, you’ll see that the finally clause is not executed, but if you comment out the call to setDaemon(), you’ll see the finally clause is executed.
Coding variations
即在构造器里启动自己
public class SimpleThread extends Thread { private int countDown = 5; private static int threadCount = 0; public SimpleThread() { // Store the Thread name: super(Integer.toString(++threadCount)); start(); } public String toString() { return "#" + getName() + "(" + countDown + "),"; } public void run() { while(true) { System.out.print(this); if(--countDown == 0) return; } } public static void main(String[] args) { for(int i=0;i<5;i++) new SimpleThread(); }}
public class SelfManager implements Runnable{ private int countDown = 5; private Thread t = new Thread(this); public SelfManager() { t.start(); } public String toString() { return Thread.currentThread().getName() + "(" + countDown + ")"; } @Override public void run() { while(true) { System.out.println(this); if(--countDown == 0) { return; } } } public static void main(String[] args) { for(int i=0;i<5;i++) { new SelfManager(); } }}
This example is quite simple and therefore probably safe, but you should be aware that starting threads inside a constructor can be quite problematic, because another task might start executing before the constructor has completed, which means the task may be able to access the object in an unstable state.
Joining a thread
If a thread calls t.join() on another thread t, then the calling thread is suspended until the target thread t finished(when t.isAlive() is false).
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 compeleted"); }}public class Joining { public static void main(String[] args) { Sleeper sleepy = new Sleeper("Sleepy", 1500), grumpy = new Sleeper("Grumpy", 1500); Joiner doper = new Joiner("Doper", sleepy), doc = new Joiner("Doc", grumpy); grumpy.interrupt(); }}
运行结果:
When another thread calls interrupt() on this thread, a flag is set to indicate that the thread has been interrupted. However, this flag is cleared when the exception is caught, so the result will always be false inside the catch clause.
- Thinking In Java 之 多线程 1
- Thinking in Java 之 多线程 2
- Thinking in Java 之 多线程 3
- Thinking In Java 之 多线程 4
- Java多线程之使用执行器(Executors)(Thinking in Java)
- Thinking in java:多线程详解
- Thinking in Java--Java多线程学习笔记(1)
- Thinking in java(1)
- Thinking in java-1
- Thinking in Java(1)
- [Thinking in JAVA] JAVA多线程的学习
- Thinking in Java 之String
- Thinking in Java之Interfaces
- Thinking in java之接口
- Thinking in Java---多线程学习笔记(2)
- thinking in java-chap 1
- thinking in java 读书笔记1
- Thinking in Java 读书笔记 1
- 合并两棵二叉树
- API安全设计
- 隔行扫描(interlaced)与逐行扫描(progressive)的图像对比
- 给大家上点儿干货
- 7台主机模拟DNS架构
- Thinking In Java 之 多线程 1
- 单例模式
- Hibernate监听用户操作日志
- 冒泡排序 bubble sort
- JAVA设计模式 单例模式
- jQuery动态效果
- Packets
- 结合FME利用倾斜三维模型数据成果生成DSM等数据产品
- centos postgresql