易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--比直接看书快N倍的速度掌握知识点--第21章 并发(一)
第21章 并发/21.2 基本的线程机制
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第21章 并发/21.2 基本的线程机制/21.2.1 定义任务
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
//: concurrency/LiftOff.java
// Demonstration of the Runnable interface.
package concurrency;
public class LiftOff implements Runnable {
protected int countDown = 10; // Default
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!") + "), ";
}
public void run() {
while(countDown-- > 0) {
System.out.print(status());
/**
* 将CPU从一个线程转移到另外线程
*/
Thread.yield();
}
}
} ///:~
-
//: concurrency/MainThread.java
package concurrency;
public class MainThread {
public static void main(String[] args) {
LiftOff launch = new LiftOff();
launch.run();
}
} /* Output:
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!),
*///:~
第21章 并发/21.2 基本的线程机制/21.2.2 Thread类
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
单个线程:
//: concurrency/BasicThreads.java
// The most basic use of the Thread class.
package concurrency;
public class BasicThreads {
public static void main(String[] args) {
/**
* 将多线程任务提交给 Thread
*/
Thread t = new Thread(new LiftOff());
t.start();
System.out.println("Waiting for LiftOff");
}
} /* Output: (90% match)
Waiting for LiftOff
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!),
*///:~
-
多个线程:
//: concurrency/MoreBasicThreads.java
// Adding more threads.
package concurrency;
public class MoreBasicThreads {
public static void main(String[] args) {
/**
* 产生5个进程同时执行
*/
for(int i = 0; i < 5; i++)
new Thread(new LiftOff()).start();
System.out.println("Waiting for LiftOff");
}
} /* Output: (Sample)
Waiting for LiftOff
#0(9), #1(9), #2(9), #3(9), #4(9), #0(8), #1(8), #2(8), #3(8), #4(8), #0(7), #1(7), #2(7), #3(7), #4(7), #0(6), #1(6), #2(6), #3(6), #4(6), #0(5), #1(5), #2(5), #3(5), #4(5), #0(4), #1(4), #2(4), #3(4), #4(4), #0(3), #1(3), #2(3), #3(3), #4(3), #0(2), #1(2), #2(2), #3(2), #4(2), #0(1), #1(1), #2(1), #3(1), #4(1), #0(Liftoff!), #1(Liftoff!), #2(Liftoff!), #3(Liftoff!), #4(Liftoff!),
*///:~
第21章 并发/21.2 基本的线程机制/21.2.3 使用Executor(执行器)
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 概念:在客户端和任务执行之间提供一个间接层,由Executor直接执行任务,而不是客户端
-
高速缓存线程池:
//: concurrency/CachedThreadPool.java
package concurrency;
import java.util.concurrent.*;
public class CachedThreadPool {
public static void main(String[] args) {
/**
* newCachedThreadPool:高速缓存线程池
*/
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
} /* Output: (Sample)
#0(9), #0(8), #1(9), #2(9), #3(9), #4(9), #0(7), #1(8), #2(8), #3(8), #4(8), #0(6), #1(7), #2(7), #3(7), #4(7), #0(5), #1(6), #2(6), #3(6), #4(6), #0(4), #1(5), #2(5), #3(5), #4(5), #0(3), #1(4), #2(4), #3(4), #4(4), #0(2), #1(3), #2(3), #3(3), #4(3), #0(1), #1(2), #2(2), #3(2), #4(2), #0(Liftoff!), #1(1), #2(1), #3(1), #4(1), #1(Liftoff!), #2(Liftoff!), #3(Liftoff!), #4(Liftoff!),
*///:~
-
按数量申请线程池:
//: concurrency/FixedThreadPool.java
package concurrency;
import java.util.concurrent.*;
public class FixedThreadPool {
public static void main(String[] args) {
// Constructor argument is number of threads:
/**
* 申请5个线程资源
*/
ExecutorService exec = Executors.newFixedThreadPool(5);
for(int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
} /* Output: (Sample)
#0(9), #0(8), #1(9), #2(9), #3(9), #4(9), #0(7), #1(8), #2(8), #3(8), #4(8), #0(6), #1(7), #2(7), #3(7), #4(7), #0(5), #1(6), #2(6), #3(6), #4(6), #0(4), #1(5), #2(5), #3(5), #4(5), #0(3), #1(4), #2(4), #3(4), #4(4), #0(2), #1(3), #2(3), #3(3), #4(3), #0(1), #1(2), #2(2), #3(2), #4(2), #0(Liftoff!), #1(1), #2(1), #3(1), #4(1), #1(Liftoff!), #2(Liftoff!), #3(Liftoff!), #4(Liftoff!),
*///:~
-
申请单个线程:
//: concurrency/SingleThreadExecutor.java
package concurrency;
import java.util.concurrent.*;
public class SingleThreadExecutor {
public static void main(String[] args) {
/**
* newSingleThreadExecutor:申请单个线程
*/
ExecutorService exec =
Executors.newSingleThreadExecutor();
for(int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
} /* Output:
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!), #1(9), #1(8), #1(7), #1(6), #1(5), #1(4), #1(3), #1(2), #1(1), #1(Liftoff!), #2(9), #2(8), #2(7), #2(6), #2(5), #2(4), #2(3), #2(2), #2(1), #2(Liftoff!), #3(9), #3(8), #3(7), #3(6), #3(5), #3(4), #3(3), #3(2), #3(1), #3(Liftoff!), #4(9), #4(8), #4(7), #4(6), #4(5), #4(4), #4(3), #4(2), #4(1), #4(Liftoff!),
*///:~
-
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!), #1(9), #1(8), #1(7), #1(6), #1(5), #1(4), #1(3), #1(2), #1(1), #1(Liftoff!), #2(9), #2(8), #2(7), #2(6), #2(5), #2(4), #2(3), #2(2), #2(1), #2(Liftoff!), #3(9), #3(8), #3(7), #3(6), #3(5), #3(4), #3(3), #3(2), #3(1), #3(Liftoff!), #4(9), #4(8), #4(7), #4(6), #4(5), #4(4), #4(3), #4(2), #4(1), #4(Liftoff!),
-
第21章 并发/21.2 基本的线程机制/21.2.4 从任务中产生返回值
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
//: concurrency/CallableDemo.java
package concurrency;
import java.util.concurrent.*;
import java.util.*;
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// /**
// * 当线程在活动之前或活动期间处于正在等待、休眠或占用状态且该线程被中断时,抛出该异常。有时候,一种方法可能希望测试当前线程是否已被中断,如果已被中断,则立即抛出此异常。下列代码可以达到这种效果:
// if (Thread.interrupted()) // Clears interrupted status!
// throw new InterruptedException();
//
// */
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
return "result of TaskWithResult " + id;
}
}
public class CallableDemo {
public static void main(String[] args) {
/**
* 这里的 newCachedThreadPool 和 实现 Runnable是一样的
*/
ExecutorService exec = Executors.newCachedThreadPool();
/**
* Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。
*/
ArrayList<Future<String>> results =
new ArrayList<Future<String>>();
for(int i = 0; i < 10; i++)
/**
* 1.Callable 与 Runnable不同的是,Runnable 用 execute 进行调用,而 Callable 用 submit 进行调用
* 2.用results保存计算结果
*/
results.add(exec.submit(new TaskWithResult(i)));
for(Future<String> fs : results)
try {
// get() blocks until completion:
/**
* 通过fs.get() 获取计算结果,如果没结束,则等待
*/
System.out.println(fs.get());
} catch(InterruptedException e) {
System.out.println(e);
return;
} catch(ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
} /* Output:
result of TaskWithResult 0
result of TaskWithResult 1
result of TaskWithResult 2
result of TaskWithResult 3
result of TaskWithResult 4
result of TaskWithResult 5
result of TaskWithResult 6
result of TaskWithResult 7
result of TaskWithResult 8
result of TaskWithResult 9
*///:~
第21章 并发/21.2 基本的线程机制/21.2.5 休眠
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
重点代码:
/**
* NANOSECONDS:纳秒
* MICROSECONDS:微妙
* MILLISECONDS:毫秒
* SECONDS:秒
* 转换关系:
* NANOSECONDS = 1/1000*MICROSECONDS
* MICROSECONDS = 1/1000*MILLISECONDS
* MILLISECONDS = 1/1000*SECONDS
*/
TimeUnit.MILLISECONDS.sleep(100);
第21章 并发/21.2 基本的线程机制/21.2.6 优先级
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
概念:优先级将线程的重要性传递给调度器,使优先级高的线程先执行,优先级较低的线程后执行,但是高低线程都会执行,不会产生死锁
//: concurrency/SimplePriorities.java
// Shows the use of thread priorities.
package concurrency;
import java.util.concurrent.*;
public class SimplePriorities implements Runnable {
private int countDown = 5;
/**
* volatile:多线程相关 变量在同一个时间只能被一个线程访问
*/
private volatile double d; // No optimization
private int priority;
public SimplePriorities(int priority) {
this.priority = priority;
}
public String toString() {
/**
* Thread.currentThread()打印结果:
* Thread[pool-1-thread-6,10,main]
*
1. pool-1:表示的池1
2. thread-6:表示第6个线程
3. 10:优先级
4. main:线程发起方法
*/
return Thread.currentThread() + ": " + countDown;
}
public void run() {
/**
* 设置线程优先级
*/
Thread.currentThread().setPriority(priority);
while(true) {
// An expensive, interruptable operation:
for(int i = 1; i < 100000; i++) {
d += (Math.PI + Math.E) / (double)i;
if(i % 1000 == 0)
/**
* yield:建议相同优先级的线程可以执行,但是并不是强制
*/
Thread.yield();
}
/**
* 调用方法 String toString() 打印当前线程
*/
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++){
/**
* 初始化调用5个同级别线程
*/
exec.execute(
new SimplePriorities(Thread.MIN_PRIORITY));
}
/**
* 再调用一个高级别线程
*/
exec.execute(
new SimplePriorities(Thread.MAX_PRIORITY));
exec.shutdown();
}
} /* Output: (70% match)
Thread[pool-1-thread-6,10,main]: 5
Thread[pool-1-thread-6,10,main]: 4
Thread[pool-1-thread-6,10,main]: 3
Thread[pool-1-thread-6,10,main]: 2
Thread[pool-1-thread-6,10,main]: 1
Thread[pool-1-thread-3,1,main]: 5
Thread[pool-1-thread-2,1,main]: 5
Thread[pool-1-thread-1,1,main]: 5
Thread[pool-1-thread-5,1,main]: 5
Thread[pool-1-thread-4,1,main]: 5
...
*///:~
-
-
Thread.currentThread() 打印结果 Thread[pool-1-thread-6,10,main]
- pool-1:表示的池1
- thread-6:表示第6个线程
- 10:优先级
- main:线程发起方法
-
Thread[pool-1-thread-2,1,main]: 5
Thread[pool-1-thread-6,10,main]: 5
Thread[pool-1-thread-4,1,main]: 5
Thread[pool-1-thread-3,1,main]: 5
Thread[pool-1-thread-1,1,main]: 5
Thread[pool-1-thread-5,1,main]: 5
Thread[pool-1-thread-4,1,main]: 4
Thread[pool-1-thread-2,1,main]: 4
Thread[pool-1-thread-6,10,main]: 4
Thread[pool-1-thread-4,1,main]: 3
Thread[pool-1-thread-2,1,main]: 3
Thread[pool-1-thread-3,1,main]: 4
Thread[pool-1-thread-1,1,main]: 4
Thread[pool-1-thread-5,1,main]: 4
Thread[pool-1-thread-4,1,main]: 2
Thread[pool-1-thread-2,1,main]: 2
Thread[pool-1-thread-4,1,main]: 1
Thread[pool-1-thread-6,10,main]: 3
Thread[pool-1-thread-3,1,main]: 3
Thread[pool-1-thread-2,1,main]: 1
Thread[pool-1-thread-5,1,main]: 3
Thread[pool-1-thread-1,1,main]: 3
Thread[pool-1-thread-6,10,main]: 2
Thread[pool-1-thread-3,1,main]: 2
Thread[pool-1-thread-1,1,main]: 2
Thread[pool-1-thread-5,1,main]: 2
Thread[pool-1-thread-6,10,main]: 1
Thread[pool-1-thread-3,1,main]: 1
Thread[pool-1-thread-1,1,main]: 1
Thread[pool-1-thread-5,1,main]: 1
-
Thread.currentThread() 打印结果 Thread[pool-1-thread-6,10,main]
第21章 并发/21.2 基本的线程机制/21.2.7 让步
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第21章 并发/21.2 基本的线程机制/21.2.8 后台线程
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 概念:指的是程序结束后自动退出的线程
-
//: concurrency/SimpleDaemons.java
// Daemon threads don't prevent the program from ending.
package concurrency;
import java.util.concurrent.*;
import static net.mindview.util.Print.*;
public class SimpleDaemons implements Runnable {
public void run() {
try {
/**
* 这里是死循环,但是只要main函数执行完成后退出,则线程也自动结束
*/
while(true) {
TimeUnit.MILLISECONDS.sleep(100);
print(Thread.currentThread() + " " + this);
}
} catch(InterruptedException e) {
print("sleep() interrupted");
}
}
public static void main(String[] args) throws Exception {
for(int i = 0; i < 10; i++) {
Thread daemon = new Thread(new SimpleDaemons());
/**
* setDaemon:设置为后台线程,而且必须在star之前设置
*/
daemon.setDaemon(true); // Must call before start()
daemon.start();
}
print("All daemons started");
TimeUnit.MILLISECONDS.sleep(100);
}
} /* Output: (Sample)
All daemons started
Thread[Thread-0,5,main] [email protected]
Thread[Thread-1,5,main] [email protected]
Thread[Thread-2,5,main] [email protected]
Thread[Thread-3,5,main] [email protected]
Thread[Thread-4,5,main] [email protected]
Thread[Thread-5,5,main] [email protected]
Thread[Thread-6,5,main] [email protected]
Thread[Thread-7,5,main] [email protected]
Thread[Thread-8,5,main] [email protected]
Thread[Thread-9,5,main] [email protected]
...
*///:~
-
工厂类后台进程:
-
//: net/mindview/util/DaemonThreadFactory.java
package net.mindview.util;
import java.util.concurrent.*;
public class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
/**
* 通过 DaemonThreadFactory 创建的所有线程都是 后台进程
*/
t.setDaemon(true);
return t;
}
} ///:~
-
//: concurrency/DaemonFromFactory.java
// Using a Thread Factory to create daemons.
package concurrency;
import java.util.concurrent.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
public class DaemonFromFactory implements Runnable {
public void run() {
try {
while(true) {
TimeUnit.MILLISECONDS.sleep(100);
print(Thread.currentThread() + " " + this);
}
} catch(InterruptedException e) {
print("Interrupted");
}
}
public static void main(String[] args) throws Exception {
/**
* 这里的线程执行器 Executors 通过 线程工厂类进行初始化,
* 由于 DaemonThreadFactory 的线程都是默认为后台线程,
* 所以exec.execute执行的都是后台线程
* 对于工厂类,先执行:ThreadFactory.public Thread newThread(Runnable r)
* 再执行exec.execute
*/
ExecutorService exec = Executors.newCachedThreadPool(
new DaemonThreadFactory());
for(int i = 0; i < 10; i++)
/**
* 1.执行创建操作,而且这个创建是基于DaemonThreadFactory
* 2.执行DaemonFromFactory.run操作
*/
exec.execute(new DaemonFromFactory());
print("All daemons started");
TimeUnit.MILLISECONDS.sleep(100); // Run for a while
}
} /* (Execute to see output) *///:~
-
-
父线程为后台线程,那由它所创建的线程都默认是后台线程:
//: concurrency/Daemons.java
// Daemon threads spawn other daemon threads.
package concurrency;
import java.util.concurrent.*;
import static net.mindview.util.Print.*;
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();
printnb("DaemonSpawn " + i + " started, ");
}
for(int i = 0; i < t.length; i++)
printnb("t[" + i + "].isDaemon() = " +
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 Exception {
Thread d = new Thread(new Daemon());
/**
* 将线程设置为后台进程,那么该线程所创建的其它线程自动设置为后台进程
*/
d.setDaemon(true);
d.start();
printnb("d.isDaemon() = " + d.isDaemon() + ", ");
// Allow the daemon threads to
// finish their startup processes:
TimeUnit.SECONDS.sleep(1);
}
} /* Output: (Sample)
d.isDaemon() = true, DaemonSpawn 0 started, DaemonSpawn 1 started, DaemonSpawn 2 started, DaemonSpawn 3 started, DaemonSpawn 4 started, DaemonSpawn 5 started, DaemonSpawn 6 started, DaemonSpawn 7 started, DaemonSpawn 8 started, DaemonSpawn 9 started, t[0].isDaemon() = true, t[1].isDaemon() = true, t[2].isDaemon() = true, t[3].isDaemon() = true, t[4].isDaemon() = true, t[5].isDaemon() = true, t[6].isDaemon() = true, t[7].isDaemon() = true, t[8].isDaemon() = true, t[9].isDaemon() = true,
*///:~
-
对于后台线程,finally子句也可能不会执行:
//: concurrency/DaemonsDontRunFinally.java
// Daemon threads don't run the finally clause
package concurrency;
import java.util.concurrent.*;
import static net.mindview.util.Print.*;
class ADaemon implements Runnable {
public void run() {
try {
print("Starting ADaemon");
TimeUnit.SECONDS.sleep(1);
} catch(InterruptedException e) {
print("Exiting via InterruptedException");
} finally {
/**
* 这里的finally不一定会执行,因为main一旦退出,作为后台线程也会马上退出
*/
print("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);
}
} /* Output:
Starting ADaemon
*///:~
第21章 并发/21.2 基本的线程机制/21.2.9 编码的变体--内部类
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- Thread创建对象通过两种方式:
-
//: concurrency/ThreadVariations.java
// Creating threads with inner classes.
package concurrency;
import java.util.concurrent.*;
import static net.mindview.util.Print.*;
// Using a named inner class:
class InnerThread1 {
private int countDown = 5;
private Inner inner;
/**
* 显式内部类:Inner 实现 Thread
* @author Administrator
*
*/
private class Inner extends Thread {
Inner(String name) {
super(name);
start();
}
public void run() {
try {
while(true) {
print(this);
if(--countDown == 0) return;
sleep(10);
}
} catch(InterruptedException e) {
print("interrupted");
}
}
public String toString() {
return getName() + ": " + countDown;
}
}
public InnerThread1(String name) {
inner = new Inner(name);
}
}
// Using an anonymous inner class:
class InnerThread2 {
private int countDown = 5;
private Thread t;
public InnerThread2(String name) {
/**
* 隐式内部类 :Thread
*/
t = new Thread(name) {
public void run() {
try {
while(true) {
print(this);
if(--countDown == 0) return;
sleep(10);
}
} catch(InterruptedException e) {
print("sleep() interrupted");
}
}
public String toString() {
return getName() + ": " + countDown;
}
};
t.start();
}
}
// Using a named Runnable implementation:
class InnerRunnable1 {
private int countDown = 5;
private Inner inner;
/**
* 显式内部类:Inner 实现 Runnable
* @author Administrator
*
*/
private class Inner implements Runnable {
Thread t;
Inner(String name) {
t = new Thread(this, name);
t.start();
}
public void run() {
try {
while(true) {
print(this);
if(--countDown == 0) return;
TimeUnit.MILLISECONDS.sleep(10);
}
} catch(InterruptedException e) {
print("sleep() interrupted");
}
}
public String toString() {
return t.getName() + ": " + countDown;
}
}
public InnerRunnable1(String name) {
inner = new Inner(name);
}
}
// Using an anonymous Runnable implementation:
class InnerRunnable2 {
private int countDown = 5;
private Thread t;
public InnerRunnable2(String name) {
/**
* 隐式内部类:通过 new Runnable()实现
*/
t = new Thread(new Runnable() {
public void run() {
try {
while(true) {
print(this);
if(--countDown == 0) return;
TimeUnit.MILLISECONDS.sleep(10);
}
} catch(InterruptedException e) {
print("sleep() interrupted");
}
}
public String toString() {
return Thread.currentThread().getName() +
": " + countDown;
}
}, name);
t.start();
}
}
// A separate method to run some code as a task:
class ThreadMethod {
private int countDown = 5;
private Thread t;
private String name;
public ThreadMethod(String name) { this.name = name; }
public void runTask() {
if(t == null) {
/**
* 隐式内部类
*/
t = new Thread(name) {
public void run() {
try {
while(true) {
print(this);
if(--countDown == 0) return;
sleep(10);
}
} catch(InterruptedException e) {
print("sleep() interrupted");
}
}
public String toString() {
return getName() + ": " + countDown;
}
};
t.start();
}
}
}
public class ThreadVariations {
public static void main(String[] args) {
new InnerThread1("InnerThread1");
new InnerThread2("InnerThread2");
new InnerRunnable1("InnerRunnable1");
new InnerRunnable2("InnerRunnable2");
new ThreadMethod("ThreadMethod").runTask();
}
} /* (Execute to see output) *///:~
第21章 并发/21.2 基本的线程机制/21.2.9 编码的变体--直接继承Thread
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第21章 并发/21.2 基本的线程机制/21.2.11 加入一个线程
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- join用于在其它线程之上执行某个线程,其它线程要在这个线程执行完成后才能接着执行
- join可以带超时参数,超过该时间后,无论线程是否结束都返回
- 也可以调用interrupt方法中断join发起的线程
-
//: concurrency/SimpleThread.java
// Inheriting directly from the Thread class.
package concurrency;
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() {
/**
* getName:获取线程名词
*/
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();
}
} /* Output:
#1(5), #1(4), #1(3), #1(2), #1(1), #2(5), #2(4), #2(3), #2(2), #2(1), #3(5), #3(4), #3(3), #3(2), #3(1), #4(5), #4(4), #4(3), #4(2), #4(1), #5(5), #5(4), #5(3), #5(2), #5(1),
*///:~
第21章 并发/21.2 基本的线程机制/21.2.12 创建有响应的用户界面
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
//: concurrency/Joining.java
// Understanding join().
package concurrency;
import static net.mindview.util.Print.*;
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) {
/*
* 休眠期间被中断抛出本异常
*/
print(getName() + " was interrupted. " +
"isInterrupted(): " + isInterrupted());
return;
}
print(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线程在this线程之上执行,这个时候this线程将被挂起
*因为sleeper进程处于睡眠状态,所以this要等待sleeper结束后再执行
*/
sleeper.join();
System.out.println(getName()+":Joiner.join");
} catch(InterruptedException e) {
print("this.Interrupted");
}
print(getName() + " join completed");
}
}
public class Joining {
public static void main(String[] args) {
Sleeper
sleepy = new Sleeper("Sleepy", 1500),
grumpy = new Sleeper("Grumpy", 1500);
Joiner
dopey = new Joiner("Dopey", sleepy),
doc = new Joiner("Doc", grumpy);
/**
* interrupt:中断 grumpy线程,由于grumpy被中断,所以doc能得到立刻执行
*/
grumpy.interrupt();
}
} /* Output:
Grumpy was interrupted. isInterrupted(): false
Doc join completed
Sleepy has awakened
Dopey join completed
*///:~
第21章 并发/21.2 基本的线程机制/21.2.13 线程组
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第21章 并发/21.2 基本的线程机制/21.2.14 捕捉异常-1.使用特定未能捕捉的异常
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
实现未能捕捉的异常:
class MyUncaughtExceptionHandler implements
Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
-
//: concurrency/CaptureUncaughtException.java
package concurrency;
import java.util.concurrent.*;
class ExceptionThread2 implements Runnable {
public void run() {
Thread t = Thread.currentThread();
System.out.println("run() by " + t);
System.out.println(
/**
* getUncaughtExceptionHandler:返回该线程由于未捕获到异常而突然终止时调用的处理程序
*/
"eh2222 = " + t.getUncaughtExceptionHandler());
throw new RuntimeException();
}
}
class MyUncaughtExceptionHandler implements
Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
System.out.println("caught " + e);
}
}
/**
* 实现线程工厂类
* @author Administrator
*
*/
class HandlerThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
System.out.println(this + " creating new Thread");
Thread t = new Thread(r);
System.out.println("created " + t);
/**
* 设置未捕捉错误
*/
t.setUncaughtExceptionHandler(
new MyUncaughtExceptionHandler());
/**
* 打印未捕捉错误
*/
System.out.println(
"eh111 = " + t.getUncaughtExceptionHandler());
return t;
}
}
public class CaptureUncaughtException {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool(
new HandlerThreadFactory());
exec.execute(new ExceptionThread2());
}
} /* Output: (90% match)
[email protected] creating new Thread
created Thread[Thread-0,5,main]
eh = [email protected]
run() by Thread[Thread-0,5,main]
eh = [email protected]
caught java.lang.RuntimeException
*///:~
第21章 并发/21.2 基本的线程机制/21.2.14 捕捉异常-2.使用默认捕捉未能异常
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
捕捉异常-2.使用默认捕捉未能异常:
//: concurrency/ExceptionThread.java
// {ThrowsException}
package concurrency;
import java.util.concurrent.*;
public class ExceptionThread implements Runnable {
public void run() {
throw new RuntimeException();
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ExceptionThread());
}
} ///:~
第21章 并发/21.3 共享受限资源
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第21章 并发/21.3 共享受限资源/21.3.1 不正确地访问资源
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
//: concurrency/IntGenerator.java
package concurrency;
public abstract class IntGenerator {
private volatile boolean canceled = false;
public abstract int next();
// Allow this to be canceled:
public void cancel() { canceled = true; }
public boolean isCanceled() { return canceled; }
} ///:~
-
//: concurrency/EvenChecker.java
package concurrency;
import java.util.concurrent.*;
/**
* EvenChecker:事件消费者
* @author Administrator
*
*/
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(); // Cancels all EvenCheckers
}
}
}
// Test any type of IntGenerator:
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();
}
// Default value for count:
public static void test(IntGenerator gp) {
test(gp, 10);
}
} ///:~
-
//: concurrency/EvenGenerator.java
// When threads collide.
package concurrency;
/**
* @author Administrator
*
*/
public class EvenGenerator extends IntGenerator {
private int currentEvenValue = 0;
/**
* currentEvenValue 只由一个对象持有的,但是 next 会被多个线程调用,也就是 currentEvenValue 属于多个线程的,那么currentEvenValue可能同时被多个线程修改
* 所有不能保证每次next方法后都是偶数
*/
public int next() {
++currentEvenValue; // Danger point here!
++currentEvenValue;
return currentEvenValue;
}
public static void main(String[] args) {
EvenChecker.test(new EvenGenerator());
}
} /* Output: (Sample)
Press Control-C to exit
89476993 not even!
89476993 not even!
*///:~
-
* currentEvenValue 只由一个对象持有的,但是 next 会被多个线程调用,也就是 currentEvenValue 属于多个线程的,那么currentEvenValue可能同时被多个线程修改
* 所有不能保证每次next方法后都是偶数
*/
public int next() {
++currentEvenValue; // Danger point here!
++currentEvenValue;
return currentEvenValue;
}
-
第21章 并发/21.3 共享受限资源/21.3.2 解决资源共享竞争--1.synchronized
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
-
//: concurrency/SynchronizedEvenGenerator.java
// Simplifying mutexes with the synchronized keyword.
// {RunByHand}
package concurrency;
public class
SynchronizedEvenGenerator extends IntGenerator {
private int currentEvenValue = 0;
public synchronized int next() {
++currentEvenValue;
Thread.yield(); // Cause failure faster
++currentEvenValue;
return currentEvenValue;
}
public static void main(String[] args) {
EvenChecker.test(new SynchronizedEvenGenerator());
}
} ///:~
- 其它代码参照: 第21章 并发/21.3 共享受限资源/21.3.1 不正确地访问资源
-
第21章 并发/21.3 共享受限资源/21.3.2 解决资源共享竞争--2.使用锁Lock
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
//: concurrency/MutexEvenGenerator.java
// Preventing thread collisions with mutexes.
// {RunByHand}
package concurrency;
import java.util.concurrent.locks.*;
public class MutexEvenGenerator extends IntGenerator {
private int currentEvenValue = 0;
private Lock lock = new ReentrantLock();
public int next() {
/**
* 使用 lock 锁定 try部分内容,而且try中必须出现return,防止过早执行unlock
*/
lock.lock();
try {
++currentEvenValue;
Thread.yield(); // Cause failure faster
++currentEvenValue;
return currentEvenValue;
} finally {
/**
* 不管怎么样,必须进行解锁操作
*/
lock.unlock();
}
}
public static void main(String[] args) {
EvenChecker.test(new MutexEvenGenerator());
}
} ///:~
第21章 并发/21.3 共享受限资源/21.3.3 原子性和易变性
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- volatile
-
错误的原子性:
//: concurrency/AtomicityTest.java
package concurrency;
import java.util.concurrent.*;
public class AtomicityTest implements Runnable {
private int i = 0;
public synchronized int getValue() { return i; }
private synchronized void evenIncrement() {
i++;
i++;
System.out.println("写入:"+i);
}
public void run() {
while(true){
evenIncrement();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest();
exec.execute(at);
while(true) {
/**
* getValue()可能取到了中间过程的值, 也就是evenIncrement有两次i++,当执行完第一个i++后该值就被getValue取到
* 那如何保障getValue能取到正确的值呢?
* getValue:也要加上 synchronized,synchronized 保障 方法对同一个变量的读写原子性
*/
int val = at.getValue();
System.out.println("读取:"+val);
if(val % 2 != 0) {
System.out.println(val);
System.exit(0);
}
}
}
} /* Output: (Sample)
191583767
*///:~
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest();
exec.execute(at);
while(true) {
/**
* getValue()可能取到了中间过程的值, 也就是evenIncrement有两次i++,当执行完第一个i++后该值就被getValue取到
* 那如何保障getValue能取到正确的值呢?
* getValue:也要加上 synchronized,synchronized 保障 方法对同一个变量的读写原子性
*/
int val = at.getValue();
System.out.println("读取:"+val);
if(val % 2 != 0) {
System.out.println(val);
System.exit(0);
}
}
}
第21章 并发/21.3 共享受限资源/21.3.4 原子类
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- AtomicInteger :正数原子类
- AtomicLong :正数原子类
- AtomicReference::引用原子类
-
用AtomicIntegerTest代替AtomicityTest( 第21章 并发/21.3 共享受限资源/21.3.3 原子性和易变性)
//: concurrency/AtomicIntegerTest.java
package concurrency;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.*;
public class AtomicIntegerTest implements Runnable {
/**
* AtomicInteger:原子类,用来保证原子性的,所有这里的
* getValue 和 evenIncrement 没有必要加 synchronized
*/
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); // Terminate after 5 seconds
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);
}
}
}
} ///:~
第21章 并发/21.3 共享受限资源/21.3.5 临界区-用synchronized修饰部分代码,而不是整个方法
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 格式:
- 锁的范围:整个方法锁比模块锁慢
- 锁的作用:共享变量被一个线程锁住时,其它线程就会被阻塞
-
//: concurrency/CriticalSection.java
// Synchronizing blocks instead of entire methods. Also
// demonstrates protection of a non-thread-safe class
// with a thread-safe one.
package concurrency;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.*;
/**
* 坐标类:主要用来检查X和Y坐标值是否相等
* @author Administrator
*
*/
class Pair { // Not thread-safe
private int x, y;
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
public Pair() { this(0, 0); }
public int getX() { return x; }
public int getY() { return y; }
public void incrementX() { x++; }
public void incrementY() { y++; }
public String toString() {
return "x: " + x + ", y: " + y;
}
public class PairValuesNotEqualException extends RuntimeException {
public PairValuesNotEqualException() {
super("Pair values not equal: " + Pair.this);
}
}
// Arbitrary invariant -- both variables must be equal:
/**
* 如果两个坐标值不相等则抛出异常
*/
public void checkState() {
if(x != y)
throw new PairValuesNotEqualException();
}
}
// Protect a Pair inside a thread-safe class:
abstract class PairManager {
AtomicInteger checkCounter = new AtomicInteger(0);
protected Pair p = new Pair();
private List<Pair> storage =
Collections.synchronizedList(new ArrayList<Pair>());
public synchronized Pair getPair() {
// Make a copy to keep the original safe:
return new Pair(p.getX(), p.getY());
}
// Assume this is a time consuming operation
protected void store(Pair p) {
storage.add(p);
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch(InterruptedException ignore) {}
}
public String toString(){
String strResult= String.format("X=%d, Y=%d",p.getX(), p.getY());
return strResult;
}
public abstract void increment();
}
// Synchronize the entire method:
class PairManager1 extends PairManager {
/**
* 这里的synchronized针对整个方法,锁定的时间比较长
*/
public synchronized void increment() {
p.incrementX();
p.incrementY();
store(getPair());
/**
* 通过 TimeUnit.SECONDS.sleep(10); 休眠操作可以测试锁的作用,共享变量被一个线程锁住时,其它线程就会被阻塞
*/
// try {
// TimeUnit.SECONDS.sleep(10);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
}
// Use a critical section:
class PairManager2 extends PairManager {
public void increment() {
Pair temp;
/**
* synchronized:线程块控制:锁定的时间相对于整个方法锁定来说,锁定的时间稍微短点
*/
synchronized(this) {
p.incrementX();
p.incrementY();
temp = getPair();
/**
* 通过 TimeUnit.SECONDS.sleep(10); 休眠操作可以测试锁的作用,共享变量被一个线程锁住时,其它线程就会被阻塞
*/
// try {
// TimeUnit.SECONDS.sleep(10);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
store(temp);
}
}
/**
* PairManipulator:创建线程方式
* run逻辑:
* 1.自增X和Y
* 2.通过整个方法锁定或者代码块锁定两种方式
* @author Administrator
*
*/
class PairManipulator implements Runnable {
private PairManager pm;
public PairManipulator(PairManager pm) {
this.pm = pm;
}
public void run() {
while(true)
pm.increment();
}
public String toString() {
/**
* pm.getPair():获取X和Y的值
* pm.checkCounter.get():获取 AtomicInteger类的值
*/
return "Pair: " + pm.getPair() +
" checkCounter = " + pm.checkCounter.get();
}
}
/**
* PairChecker:创建线程方式
* run逻辑:
* 1.使用原子类方式实现checkCounter自增
* 2.通过getPair获取X和Y的值
* @author Administrator
*
*/
class PairChecker implements Runnable {
private PairManager pm;
public PairChecker(PairManager pm) {
this.pm = pm;
}
public void run() {
while(true) {
/**
* pm.checkCounter.incrementAndGet(): AtomicInteger类新增并且或者新值
*/
pm.checkCounter.incrementAndGet();
pm.getPair().checkState();
System.out.println(pm);
}
}
}
public class CriticalSection {
// Test the two different approaches:
static void
testApproaches(PairManager pman1, PairManager pman2) {
ExecutorService exec = Executors.newCachedThreadPool();
/**
* PairManipulator:自增X和Y
*/
PairManipulator
pm1 = new PairManipulator(pman1),
pm2 = new PairManipulator(pman2);
/**
* PairChecker:自增原子类checkCounter
*/
PairChecker
pcheck1 = new PairChecker(pman1),
pcheck2 = new PairChecker(pman2);
exec.execute(pm1);
exec.execute(pm2);
exec.execute(pcheck1);
exec.execute(pcheck2);
try {
/**
* NANOSECONDS:纳秒
* MICROSECONDS:微妙
* MILLISECONDS:毫秒
* SECONDS:秒
* 转换关系:
* NANOSECONDS = 1/1000*MICROSECONDS
* MICROSECONDS = 1/1000*MILLISECONDS
* MILLISECONDS = 1/1000*SECONDS
*/
TimeUnit.MILLISECONDS.sleep(500);
} catch(InterruptedException e) {
System.out.println("Sleep interrupted");
}
System.out.println("pm1: " + pm1 + "\npm2: " + pm2);
System.exit(0);
}
public static void main(String[] args) {
PairManager
pman1 = new PairManager1(),
pman2 = new PairManager2();
/**
* pman1:代表整个方法方式锁定线程
* pman2:代表代码块锁定线程
*/
testApproaches(pman1, pman2);
}
} /* Output: (Sample)
pm1: Pair: x: 15, y: 15 checkCounter = 272565
pm2: Pair: x: 16, y: 16 checkCounter = 3956974
*///:~
第21章 并发/21.3 共享受限资源/21.3.6 在其它对象上同步--不同对象的锁
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 同一个对象的锁,在同一个时间只能执行一段逻辑,完成后才释放给其它锁逻辑,例如: 第21章 并发/21.3 共享受限资源/21.3.3 原子性和易变性 中的 synchronized int getValue 与 synchronized void evenIncrement() 是互斥的
-
不同对象的锁相互独立,例如本例子
//: concurrency/SyncObject.java
// Synchronizing on another object.
package concurrency;
import static net.mindview.util.Print.*;
import java.util.concurrent.TimeUnit;
class DualSynch {
private Object syncObject = new Object();
/**
* f:使用方法锁
*/
public synchronized void f() {
for(int i = 0; i < 5; i++) {
print("f()");
Thread.yield();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void g() {
/**
* g:使用代码块锁,而且对象为 syncObject,这个锁与f()的synchronized锁是相互独立,因为他们是不同对象的锁
* 如果synchronized(this)换成synchronized(this),则与f()的synchronized锁是相同的,两者就是互斥,再同一个时间只能使用一个
*/
synchronized(syncObject) {
for(int i = 0; i < 5; i++) {
print("g()");
Thread.yield();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class SyncObject {
public static void main(String[] args) {
final DualSynch ds = new DualSynch();
new Thread() {
public void run() {
ds.f();
}
}.start();
ds.g();
}
} /* Output: (Sample)
g()
f()
g()
f()
g()
f()
g()
f()
g()
f()
*///:~
第21章 并发/21.3 共享受限资源/21.3.7 线程本地存储
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 概念:对每一个线程所操作的变量X都进行本地存储,使得每一个线程和当时的变量值进行关联。
- 目的:防止共享资源产生冲突的第二种方法是根除对变量的共享,那就是线程本地存储。
-
//: concurrency/ThreadLocalVariableHolder.java
// Automatically giving each thread its own storage.
package concurrency;
import java.util.concurrent.*;
import java.util.*;
class Accessor implements Runnable {
/**
* 线程ID
*/
private final int id;
public Accessor(int idn) { id = idn; }
public void run() {
while(!Thread.currentThread().isInterrupted()) {
/**
* ThreadLocalVariableHolder:本地存储对象新增操作
*/
ThreadLocalVariableHolder.increment();
System.out.println(this);
Thread.yield();
}
}
public String toString() {
return "#" + id + ": " +
ThreadLocalVariableHolder.get();
}
}
public class ThreadLocalVariableHolder {
/**
* 创建匿名内部类继承于ThreadLocal
*/
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 Exception {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++)
exec.execute(new Accessor(i));
TimeUnit.SECONDS.sleep(3); // Run for a while
exec.shutdownNow(); // All Accessors will quit
}
} /* Output: (Sample)
#0: 9259
#1: 556
#2: 6694
#3: 1862
#4: 962
#0: 9260
#1: 557
#2: 6695
#3: 1863
#4: 963
...
*///:~
-
public class ThreadLocalVariableHolder {
/**
* 创建匿名内部类继承于ThreadLocal
*/
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 Exception {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++)
exec.execute(new Accessor(i));
TimeUnit.SECONDS.sleep(3); // Run for a while
exec.shutdownNow(); // All Accessors will quit
}
》》》》》未完:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--比直接看书快N倍的速度掌握知识点--总共19章》》》》》
-