> 文章列表 > Java并发编程实战(一)

Java并发编程实战(一)

Java并发编程实战(一)

xxx系列文章

xxxx系列(1)―

xxxx系列(2)―

xxxxx系列(3)―


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

    • xxx系列文章
  • 前言
  • 一、一级标题1
  • 总结

前言

晚上刷视频刷到河北王校长的bug排除视频,校长深厚的基本功令我汗颜,需要好好学习一下多线程的相关知识了,由此开了这个系列,以极客专栏的学习为主,记下笔记,辅以processon画流程图,尽可能提高自己的并发编程水平

参考链接:


一、一级标题1

  Java 里 synchronized、wait()/notify() 相关的知识很琐碎,看懂难,会用更难。但实际上 synchronized、wait()、notify() 不过是操作系统领域里管程模型的一种实现而已,Java SDK 并发包里的条件变量 Condition 也是管程里的概念,synchronized、wait()/notify()、条件变量这些知识如果单独理解,自然是管中窥豹
  管程作为一种解决并发问题的模型,是继信号量模型之后的一项重大创新,它与信号量在逻辑上是等价的(可以用管程实现信号量,也可以用信号量实现管程),但是相比之下管程更易用。而且,很多编程语言都支持管程   

其实并发编程可以总结为三个核心问题:分工、同步、互斥。
  
  所谓分工指的是如何高效地拆解任务并分配给线程,而同步指的是线程之间如何协作,互斥则是保证同一时刻只允许一个线程访问共享资源。Java SDK 并发包很大部分内容都是按照这三个维度组织的,例如 Fork/Join 框架就是一种分工模式,CountDownLatch 就是一种典型的同步方式,而可重入锁则是一种互斥手段
  当把并发编程核心的问题搞清楚,再回过头来看 Java SDK 并发包,你会感觉豁然开朗,它不过是针对并发问题开发出来的工具而已,此时的 SDK 并发包可以任你“盘”了。
  而且,这三个核心问题是跨语言的,你如果要学习其他语言的并发编程类库,完全可以顺着这三个问题按图索骥。Java SDK 并发包其余的一部分则是并发容器和原子类,这些比较容易理解,属于辅助工具,其他语言里基本都能找到对应的。

2.xxx
 内容关键字,关键字onApplicationEvent,内容。


  第三段关键字
  第四段

Java并发编程实战(一)
原图中 wait 到 runnable 状态的转换中,join实际上是Thread类的方法,但这里写成了Object
Java并发编程实战(一)

jdk源码中的线程状态

public enum State {/* Thread state for a thread which has not yet started.*/NEW,/* Thread state for a runnable thread.  A thread in the runnable* state is executing in the Java virtual machine but it may* be waiting for other resources from the operating system* such as processor.*/RUNNABLE,/* Thread state for a thread blocked waiting for a monitor lock.* A thread in the blocked state is waiting for a monitor lock* to enter a synchronized block/method or* reenter a synchronized block/method after calling* {@link Object#wait() Object.wait}.*/BLOCKED,/* Thread state for a waiting thread.* A thread is in the waiting state due to calling one of the* following methods:* <ul>*   <li>{@link Object#wait() Object.wait} with no timeout</li>*   <li>{@link #join() Thread.join} with no timeout</li>*   <li>{@link LockSupport#park() LockSupport.park}</li>* </ul> <p>A thread in the waiting state is waiting for another thread to* perform a particular action. For example, a thread that has called <tt>Object.wait()</tt>* on an object is waiting for another thread to call* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on* that object. A thread that has called <tt>Thread.join()</tt>* is waiting for a specified thread to terminate.*/WAITING,/* Thread state for a waiting thread with a specified waiting time.* A thread is in the timed waiting state due to calling one of* the following methods with a specified positive waiting time:* <ul>*   <li>{@link #sleep Thread.sleep}</li>*   <li>{@link Object#wait(long) Object.wait} with timeout</li>*   <li>{@link #join(long) Thread.join} with timeout</li>*   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>*   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>* </ul>*/TIMED_WAITING,/* Thread state for a terminated thread.* The thread has completed execution.*/TERMINATED;}

Thread.init方法

 private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {if (name == null) {throw new NullPointerException("name cannot be null");}this.name = name;Thread parent = currentThread();SecurityManager security = System.getSecurityManager();if (g == null) {/* Determine if it's an applet or not *//* If there is a security manager, ask the security managerwhat to do. */if (security != null) {//获取security的ThreadGroupg = security.getThreadGroup();}/* If the security doesn't have a strong opinion of the matteruse the parent thread group. */if (g == null) {g = parent.getThreadGroup();}}//尊重线程初始化穿入的threadgroup;次选System security mananger 的 tg;再次选 parent的 tg。/* checkAccess regardless of whether or not threadgroup isexplicitly passed in. */g.checkAccess();/ Do we have the required permissions?*/if (security != null) {if (isCCLOverridden(getClass())) {security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);}}//new状态的线程会添加到ThreadGroupg.addUnstarted();this.group = g;//新线程的属性依赖于父线程this.daemon = parent.isDaemon();this.priority = parent.getPriority();if (security == null || isCCLOverridden(parent.getClass()))this.contextClassLoader = parent.getContextClassLoader();elsethis.contextClassLoader = parent.contextClassLoader;this.inheritedAccessControlContext =acc != null ? acc : AccessController.getContext();this.target = target;setPriority(priority);if (inheritThreadLocals && parent.inheritableThreadLocals != null)this.inheritableThreadLocals =ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);/* Stash the specified stack size in case the VM cares */this.stackSize = stackSize;/* Set thread ID */tid = nextThreadID();}

尊重线程初始化穿入的threadgroup;次选System security mananger 的 tg;再次选 parent的 tg。

private static synchronized long nextThreadID() {return ++threadSeqNumber;}

synchronized
一个新构造的线程对象是由其parent线程来进行空间分配的,而child线程继承了parent是否为Daemon、优先级和加载资源的contextClassLoader以及可继承的ThreadLocal,同时还会分配一个唯一的(sync)ID来标识这个child线程。至此,一个能够运行的线程对象就初始化好了,在堆内存中等待着运行。

线程对象在初始化完成之后,调用start()方法就可以启动这个线程。线程start()方法的含义是:当前线程(即parent线程)同步告知Java虚拟机,只要线程规划器空闲,应立即启动调用start()方法的线程。

//避免多线程同时启动一个线程
public synchronized void start() {/* This method is not invoked for the main method thread or "system"* group threads created/set up by the VM. Any new functionality added* to this method in the future may have to also be added to the VM. A zero status value corresponds to state "NEW".*///private volatile int threadStatus = 0;//volitile进行二次保障,synchronized已经可以保障不会同时执行if (threadStatus != 0)throw new IllegalThreadStateException();/* Notify the group that this thread is about to be started* so that it can be added to the group's list of threads* and the group's unstarted count can be decremented. */group.add(this);boolean started = false;try {//native方法,告诉操作系统分配cpu时间片完成系统调度//start0完全执行前,线程处于Ready状态start0();//完成后,只要cpu分配执行权,就处于Running状态//Running和Ready不是jdk定义的状态,统称为Runnablestarted = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {//start0如果出现异常,会直接反馈给调用线程,Main函数里面的thread.start方法。//防止我们的thread.start方法感知不到异常导致程序的错误执行/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}}

Thread.sleep()

 /* Causes the currently executing thread to sleep (temporarily cease* execution) for the specified number of milliseconds, subject to* the precision and accuracy of system timers and schedulers. The thread* does not lose ownership of any monitors.* 线程不会失去监控锁 @param  millis*         the length of time to sleep in milliseconds @throws  IllegalArgumentException*          if the value of {@code millis} is negative @throws  InterruptedException*          if any thread has interrupted the current thread. The*          <i>interrupted status</i> of the current thread is*          cleared when this exception is thrown.* 			sleep方法响应中断*/
//会释放cpu执行权
//native方法
public static native void sleep(long millis) throws InterruptedException;

Object.wait()

 /* Causes the current thread to wait until either another thread invokes the* {@link java.lang.Object#notify()} method or the* {@link java.lang.Object#notifyAll()} method for this object, or a* specified amount of time has elapsed.* <p>* The current thread must own this object's monitor.* <p>* This method causes the current thread (call it <var>T</var>) to* place itself in the wait set for this object and then to relinquish* any and all synchronization claims on this object. Thread <var>T</var>* becomes disabled for thread scheduling purposes and lies dormant* until one of four things happens:* <ul>* <li>Some other thread invokes the {@code notify} method for this* object and thread <var>T</var> happens to be arbitrarily chosen as* the thread to be awakened.* <li>Some other thread invokes the {@code notifyAll} method for this* object.* <li>Some other thread {@linkplain Thread#interrupt() interrupts}* thread <var>T</var>.* <li>The specified amount of real time has elapsed, more or less.  If* {@code timeout} is zero, however, then real time is not taken into* consideration and the thread simply waits until notified.* </ul>* The thread <var>T</var> is then removed from the wait set for this* object and re-enabled for thread scheduling. It then competes in the* usual manner with other threads for the right to synchronize on the* object; once it has gained control of the object, all its* synchronization claims on the object are restored to the status quo* ante - that is, to the situation as of the time that the {@code wait}* method was invoked. Thread <var>T</var> then returns from the* invocation of the {@code wait} method. Thus, on return from the* {@code wait} method, the synchronization state of the object and of* thread {@code T} is exactly as it was when the {@code wait} method* was invoked.* <p>* A thread can also wake up without being notified, interrupted, or* timing out, a so-called <i>spurious wakeup</i>.  While this will rarely* occur in practice, applications must guard against it by testing for* the condition that should have caused the thread to be awakened, and* continuing to wait if the condition is not satisfied.  In other words,* waits should always occur in loops, like this one:* <pre>*     synchronized (obj) {*         while (&lt;condition does not hold&gt;)*             obj.wait(timeout);*         ... // Perform action appropriate to condition*     }* </pre>* (For more information on this topic, see Section 3.2.3 in Doug Lea's* "Concurrent Programming in Java (Second Edition)" (Addison-Wesley,* 2000), or Item 50 in Joshua Bloch's "Effective Java Programming* Language Guide" (Addison-Wesley, 2001). <p>If the current thread is {@linkplain java.lang.Thread#interrupt()* interrupted} by any thread before or while it is waiting, then an* {@code InterruptedException} is thrown.  This exception is not* thrown until the lock status of this object has been restored as* described above. <p>* Note that the {@code wait} method, as it places the current thread* into the wait set for this object, unlocks only this object; any* other objects on which the current thread may be synchronized remain* locked while the thread waits.* <p>* This method should only be called by a thread that is the owner* of this object's monitor. See the {@code notify} method for a* description of the ways in which a thread can become the owner of* a monitor. @param      timeout   the maximum time to wait in milliseconds.* @throws  IllegalArgumentException      if the value of timeout is*               negative.* @throws  IllegalMonitorStateException  if the current thread is not*               the owner of the object's monitor.* @throws  InterruptedException if any thread interrupted the*             current thread before or while the current thread*             was waiting for a notification.  The <i>interrupted*             status</i> of the current thread is cleared when*             this exception is thrown.* @see        java.lang.Object#notify()* @see        java.lang.Object#notifyAll()*/public final native void wait(long timeout) throws InterruptedException;

Thread.join()
在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。

作用是阻塞当前线程的执行,等到被调用join的线程对象执行完毕才执行继续执行当前线程

public final synchronized void join(long millis)throws InterruptedException {long base = System.currentTimeMillis();long now = 0;if (millis < 0) {throw new IllegalArgumentException("timeout value is negative");}if (millis == 0) {//start开启后并且没有被终止while (isAlive()) {//wait是Object的方法,这个是父类,这个wait方法前有一个隐藏的含义,this.wait()(不是很准确)//当前线程类(Thread)有一个当前线程,当前线程(Thread类)这个对象释放了cpu,释放了锁//Thread的join方法释放的是当前调用join方法的那个对象的锁wait(0);}} else {while (isAlive()) {long delay = millis - now;if (delay <= 0) {break;}wait(delay);now = System.currentTimeMillis() - base;}}}

具体要看当前的锁对象是谁,如果是调用join方法的锁对象,则释放,否则不释放

synchronized(obj){thread.join(); //join不释放锁
}
synchronized(thread){thread.join(); //join释放锁
}
public class JoinRelase {static Object object = new Object();public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 2; i++) {Thread thread = new Thread(new SubThread(), "Daemon Thread!" + i);thread.setName("thread-" + i);thread.start();Thread.sleep(100);}}static class SubThread implements Runnable {@SneakyThrows@Overridepublic void run() {synchronized (Thread.currentThread()) {System.out.println("获取到锁!!!ThreadName: " + Thread.currentThread().getName());Thread.currentThread().join();}}}
}

总结