Java并发编程基础
来源:互联网 发布:unity3d小地图制作 编辑:程序博客网 时间:2024/05/21 11:15
线程优先级: 一共5级
线程的状态:
NEW: 初始状态,线程被创建,还未执行start()
RUNNABLE:运行状态,包括运行态和就绪态
BLOCKED:阻塞状态,表示线程阻塞于锁,阻塞在线程进入synchronized代码快的地方
WAITING:等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通知或者中断)
TIME_WAITING:超时等待状态,该状态不同于WAITING,它是可以在指定的时间自行返回的
TERMINATED: 终止状态,表示当前线程已经执行完毕。
jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。
跑一个java线程状态的程序,执行jps,获取到线程pid,然后jstack pid查看线程的状态。
Daemon线程
Daemon线程是支持型线程,主要作为后台调度或支持型工作,当java虚拟机中不存在非daemon线程时,java虚拟机将会推出。谨记,不要用finally代码块清理daemon线程,因为当java虚拟机退出时,是不会执行finallly代码块的
启动和终止线程
线程在init时,需要提供线程所需要的属性,如所属线程组,线程优先级,是否为Daemon,查看线程初始化源码,一个新构造的线程对象是由其parent线程来进行空间分配的,child继承parent的,是否为Daemon,优先级,加载资源的contextClassLoader,及inheritableThreadLocals。初始化后,线程在堆中等待运行。
start()启动线程
中断
中断可以理解为线程的一个标志位属性,许多声明抛出InterrupptedException的方法在抛出异常之前,java虚拟机会先将线程中的中断标志位清除,对于sleep中的线程,调用interrupt()方法,中断标志位会被清除,而runnable状态的线程调用interrupt()方法,中断标志位不会被清除
public class Interrupted {public static void main(String[] args){// SleepThread一直不停得尝试睡眠Thread sleepThread=new Thread(new SleepThread());sleepThread.setDaemon(true);Thread busyThread=new Thread(new BusyThread());busyThread.setDaemon(true);sleepThread.start();busyThread.start();SleepUtils.second(5);sleepThread.interrupt();busyThread.interrupt();System.out.println("SleepThread interrupted is "+ sleepThread.isInterrupted());System.out.println("BusyThread interrupted is "+busyThread.isInterrupted());SleepUtils.second(2);}static class SleepThread implements Runnable {public void run() {while (true) {SleepUtils.second(10);}}}static class BusyThread implements Runnable {public void run() {while (true) {}}}public static class SleepUtils {public static void second(long seconds) {try {Thread.sleep(seconds);} catch (InterruptedException e) {// do nothing}}}}
输出结果
SleepThread interrupted is false
BusyThread interrupted is true
过期的suspend(),resume(),和stop()
分别对线程执行暂停,重启,和停止,以suspend为例,它在暂停期间不会释放已经占有的资源(比如锁),而占着锁进入睡眠状态很容易引起死锁。所以这些方法被deprecated了,这些方法可以由wait()和notify()来代替。
安全的终止线程
可以通过interrupt或者利用boolean变量来控制是否需要停止任务
import java.util.concurrent.TimeUnit;public class Shutdown {public static void main(String[] args) throws InterruptedException {Runner one = new Runner();Thread countThread = new Thread(one, "CountThread");countThread.start();TimeUnit.SECONDS.sleep(1);countThread.interrupt();Runner two = new Runner();countThread = new Thread(two, "CountThread");countThread.start();TimeUnit.SECONDS.sleep(1);two.cancel();}public static class Runner implements Runnable {private long i;private volatile boolean on = true;public void run() {while (on && !Thread.currentThread().isInterrupted()) {i++;}System.out.println("Count i=" + i);}public void cancel() {on = false;}}}
输出:
Count i=446723267
Count i=456889859
这种通过标识位或者中断操作的方式,能够使线程在终止时有机会去清理资源,更加安全的终止线程。
线程间通信
javac Synchronized.java,对类文件进行编译,生成Synchronized.class
javap -v Sycnhronzied.class 对字节码文件进行反编译
public class Synchronized {public static void main(String[] args) {synchronized (Synchronized.class) {}m();}public static synchronized void m() {}}//反编译后代码public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: ldc #2 // class Synchronized 2: dup 3: astore_1 4: monitorenter // monitorenter: 监视器进入,获取锁 5: aload_1 6: monitorexit // monitorexit:监视器退出,释放锁 7: goto 15 10: astore_2 11: aload_1 12: monitorexit 13: aload_2 14: athrow 15: invokestatic #3 // Method m:()V 18: returnpublic static synchronized void m(); descriptor: ()V flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED Code: stack=0, locals=0, args_size=0 0: return
import java.text.SimpleDateFormat;import java.util.Date;import java.util.concurrent.TimeUnit;public class WaitNotify {static boolean flag = true;static Object lock = new Object();public static void main(String[] args) throws InterruptedException {Thread waitThread = new Thread(new Wait(), "WaitThread");waitThread.start();TimeUnit.SECONDS.sleep(1);Thread notifyThread = new Thread(new Notify(), "NotifyThread");notifyThread.start();}static class Wait implements Runnable {public void run() {// 加锁,拥有lock的monitorsynchronized (lock) {// 当条件不满足时,继续wait,并且释放lock的锁while (flag) {try {System.out.println(Thread.currentThread() + " flag is true. wait@"+ new SimpleDateFormat("HH:mm:ss").format(new Date()));lock.wait();} catch (InterruptedException e) {// do nothing}}// 条件满足,完成工作System.out.println(Thread.currentThread()+ " flag is false. running@"+ new SimpleDateFormat("HH:mm:ss").format(new Date()));}}}static class Notify implements Runnable {@Overridepublic void run() {// 加锁,拥有lock的monitorsynchronized (lock) {// 获取lock的锁,然后进行notify,通知时不会释放lock的锁,此时,线程由waiting状态变成blocked状态// 也就是从等待队列到了同步队列中// 直到当前线程释放了lock之后,WaitThread才能从wait方法中返回System.out.println(Thread.currentThread()+ " hold the lock. notify@"+ new SimpleDateFormat("HH:mm:ss").format(new Date()));lock.notify();flag = false;try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {}}synchronized (lock) {System.out.println(Thread.currentThread()+ " hold the lock again. sleep@"+ new SimpleDateFormat("HH:mm:ss").format(new Date()));try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {}}}}}
输出:
Thread[NotifyThread,5,main] hold the lock. notify@16:42:24
Thread[NotifyThread,5,main] hold the lock again. sleep@16:42:26
Thread[WaitThread,5,main] flag is false. running@16:42:28
synchronized(对象){ while(条件不满足){ 对象.wait() } 对应的逻辑处理}
synchronized(对象){ 改变条件 对象.notify()}
管道输入输出流
import java.io.IOException;import java.io.PipedReader;import java.io.PipedWriter;public class Piped {public static void main(String[] args) throws IOException {PipedWriter out = new PipedWriter();PipedReader in = new PipedReader();// 将输出流和输入流进行连接,否则在使用时会抛出IOExceptionout.connect(in);Thread printThread = new Thread(new Print(in), "PrintThread");printThread.start();int receive = 0;try {while ((receive = System.in.read()) != -1) {out.write(receive);}} finally {out.close();}}static class Print implements Runnable {private PipedReader in;public Print(PipedReader in) {this.in = in;}public void run() {int receive = 0;try {while ((receive = in.read()) != -1) {System.out.println((char) receive);}} catch (IOException e) {}}}}
对于Piped类型的流,必须先要进行绑定,也就是connect()
public class Join {public static void main(String[] args) {Thread previous = Thread.currentThread();for (int i = 0; i < 10; i++) {//每个线程拥有前一个线程的引用,需要等待前一个线程终止,才能从等待中返回Thread thread=new Thread(new Domino(previous),String.valueOf(i));thread.start();previous=thread;}System.out.println(Thread.currentThread().getName()+" terminated");}static class Domino implements Runnable {private Thread thread;public Domino(Thread thread) {this.thread = thread;}public void run() {try {thread.join();} catch (InterruptedException e) {}System.out.println(Thread.currentThread().getName() + " terminated.");}}}
输出:
0 terminated.
1 terminated.
2 terminated.
3 terminated.
4 terminated.
5 terminated.
6 terminated.
7 terminated.
8 terminated.
9 terminated.
// 加锁当前线程对象public final synchronized void join() throws InterruptedException { //条件不满足,等待 while(isAlive){ wait(0); } //条件满足,方法返回}
等待超时模式
public synchronized Object get(long millis) throws InterruptedException { long future=System.currentTimeMillis()+millis; long remaining=millis; //当超时大于0并且result返回值不满足要求时 while(result==null&&remaining>0){ wait(remaining); remaining=future-System.currentTimeMillis(); } return result;}
import java.sql.Connection;import java.util.LinkedList;public class ConnectionPool {private LinkedList<Connection> pool = new LinkedList<Connection>();public ConnectionPool(int initialSize) {if (initialSize > 0) {for (int i = 0; i < initialSize; i++) {pool.addLast(ConnectionDriver.createConnection());}}}public void releaseConnection(Connection connection) {if (connection != null) {synchronized (pool) {//连接释放后需要进行通知,其他消费者能够感知到连接池中已经归还了一个连接pool.addLast(connection);pool.notifyAll();}}}public Connection fetchConnection(long millis) throws InterruptedException{synchronized(pool){//完全超時---我理解就是millis如果设置成负数或者0,获取不到connection的话就一直等待if(millis<=0){while(pool.isEmpty()){pool.wait(0);}return pool.removeFirst();}else{long future=System.currentTimeMillis()+millis;long remaining=millis;while(pool.isEmpty()&&remaining>0){pool.wait(remaining);remaining=future-System.currentTimeMillis();}Connection result=null;result=pool.removeFirst();return result;}}}}
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.sql.Connection;import java.util.concurrent.TimeUnit;public class ConnectionDriver {// InvocationHandler 可以实现java反射static class ConnectionHandler implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {if (method.getName().equals("commit")) {TimeUnit.MILLISECONDS.sleep(100);}return null;}}public static final Connection createConnection() {return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(),new Class<?>[]{Connection.class}, new ConnectionHandler());}}
import java.sql.Connection;import java.sql.SQLException;import java.util.concurrent.CountDownLatch;import java.util.concurrent.atomic.AtomicInteger;public class ConnectionPoolTest {static ConnectionPool pool = new ConnectionPool(10);// 可以修改线程数量static int threadCount = 10;// 保证所有ConnectionRunner同时开始static CountDownLatch start = new CountDownLatch(1);// main线程会等待所有ConnectionRunner结束后才能继续执行static CountDownLatch end = new CountDownLatch(threadCount);public static void main(String[] args) throws InterruptedException {int count = 20;AtomicInteger got = new AtomicInteger();AtomicInteger notGot = new AtomicInteger();for (int i = 0; i < threadCount; i++) {Thread thread = new Thread(new ConnectionRunner(count, got, notGot));thread.start();}start.countDown();end.await();System.out.println("total invoke: " + (threadCount * count));System.out.println("got connection: " + got);System.out.println("not got connection: " + notGot);}static class ConnectionRunner implements Runnable {int count;AtomicInteger got;AtomicInteger notGot;public ConnectionRunner(int count, AtomicInteger got,AtomicInteger notGot) {this.count = count;this.got = got;this.notGot = notGot;}@Overridepublic void run() {try {start.await();} catch (InterruptedException e) {e.printStackTrace();}while (count > 0) {// 从连接池里获取连接,如果1000ms内无法获得,将返回null// 分别统计连接获取的数量got和未获取到的数量notGottry {Connection connection = pool.fetchConnection(1000);if (connection != null) {try {connection.createStatement();connection.commit();} catch (SQLException e) {}got.decrementAndGet();} else {notGot.decrementAndGet();}} catch (InterruptedException e) {} finally {count--;}}end.countDown();}}}
线程池技术及其实例
- Java并发编程基础
- Java并发编程基础
- Java并发编程基础
- Java 并发编程 基础
- Java并发编程基础
- Java并发编程基础
- Java并发编程基础
- Java并发编程基础
- Java并发编程基础
- Java并发编程:并发基础概念
- java并发编程——并发基础
- 《Java并发系列》0.并发编程基础
- Java并发编程 基础概念
- Java 并发编程 基础 一
- java并发编程的基础
- java并发编程-基础原理
- 【Java并发编程】一.基础
- Java基础--并发编程基础(1)
- Spring、Spring MVC、MyBatis 整合文件配置详解
- 身为程序员的你是不是经常说这几句话呢?
- 全世界第一款性爱机器人诞生了,简直太丧心病狂!
- 北大,STL简单整理
- 剖析url中汉字对网站优化结果的影响
- Java并发编程基础
- Linux 常见问题
- Java中的循环语句
- 简单MVP实现
- 自定义View箭头沿着圆形滑动
- 数据蒋堂 | JOIN简化
- Yann Lecun最新演讲:机器怎样进行有效学习?
- angular添加数据
- 科学研究设计五:实验设计