> 文章列表 > JUC多并发编程 初探

JUC多并发编程 初探

JUC多并发编程 初探

实现一个简单的线程

public class TreadDemo {public static void main(String[] args) {Thread thread = new Thread(()->{}, "th");thread.start();}
}

进入 start 方法:

    public synchronized void start() {if (threadStatus != 0)throw new IllegalThreadStateException();group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}}private native void start0();

Thread.c : 

java 线程是通过 start 的方法启动执行的,主要内容在 native 方法 start0中, openjdk的写 JNI 一般是一一对应的, Thread.java 对应的就是 Thread.c, start0 起始就是 JVM_StartThread。 此时查看源代码可以看到在 jvm.h 中找到了声明,jvm.cpp 中有实现

// Thread.c
static JNINativeMethod methods[] = {{"start0",           "()V",        (void *)&JVM_StartThread},{"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},{"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},{"suspend0",         "()V",        (void *)&JVM_SuspendThread},{"resume0",          "()V",        (void *)&JVM_ResumeThread},{"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},{"yield",            "()V",        (void *)&JVM_Yield},{"sleep",            "(J)V",       (void *)&JVM_Sleep},{"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},{"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},{"interrupt0",       "()V",        (void *)&JVM_Interrupt},{"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},{"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},{"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},{"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},{"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};
// jvm.cpp
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))JVMWrapper("JVM_StartThread");JavaThread *native_thread = NULL;// We cannot hold the Threads_lock when we throw an exception,// due to rank ordering issues. Example:  we might need to grab the// Heap_lock while we construct the exception.bool throw_illegal_thread_state = false;// We must release the Threads_lock before we can post a jvmti event// in Thread::start.{// Ensure that the C++ Thread and OSThread structures aren't freed before// we operate.MutexLocker mu(Threads_lock);// Since JDK 5 the java.lang.Thread threadStatus is used to prevent// re-starting an already started thread, so we should usually find// that the JavaThread is null. However for a JNI attached thread// there is a small window between the Thread object being created// (with its JavaThread set) and the update to its threadStatus, so we// have to check for thisif (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {throw_illegal_thread_state = true;} else {// We could also check the stillborn flag to see if this thread was already stopped, but// for historical reasons we let the thread detect that itself when it starts runningjlong size =java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));// Allocate the C++ Thread structure and create the native thread.  The// stack size retrieved from java is signed, but the constructor takes// size_t (an unsigned type), so avoid passing negative values which would// result in really large stacks.size_t sz = size > 0 ? (size_t) size : 0;native_thread = new JavaThread(&thread_entry, sz);// At this point it may be possible that no osthread was created for the// JavaThread due to lack of memory. Check for this situation and throw// an exception if necessary. Eventually we may want to change this so// that we only grab the lock if the thread was created successfully -// then we can also do this check and throw the exception in the// JavaThread constructor.if (native_thread->osthread() != NULL) {// Note: the current thread is not being used within "prepare".native_thread->prepare(jthread);}}}if (throw_illegal_thread_state) {THROW(vmSymbols::java_lang_IllegalThreadStateException());}assert(native_thread != NULL, "Starting null thread?");if (native_thread->osthread() == NULL) {// No one should hold a reference to the 'native_thread'.delete native_thread;if (JvmtiExport::should_post_resource_exhausted()) {JvmtiExport::post_resource_exhausted(JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,"unable to create new native thread");}THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),"unable to create new native thread");}Thread::start(native_thread);JVM_END
// Thread.cpp
void Thread::start(Thread* thread) {trace("start", thread);// Start is different from resume in that its safety is guaranteed by context or// being called from a Java method synchronized on the Thread object.if (!DisableStartThread) {if (thread->is_Java_thread()) {// Initialize the thread state to RUNNABLE before starting this thread.// Can not set it after the thread started because we do not know the// exact thread state at that time. It could be in MONITOR_WAIT or// in SLEEPING or some other state.java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),java_lang_Thread::RUNNABLE);}os::start_thread(thread);}
}

基本概念

并发(concurrent):

  • 是在同一实体上的多个事件
  • 是在同一台处理器上"同时" 处理多个任务
  • 同一时刻,其实只有一个事件在发生

并行(parallel):

  • 是在不同实体上的多个事件
  • 是在多台处理器上同时处理多个任务
  • 同一时刻, 大家真的都在做事情,你做你的,我做我的

进程:

在系统中运行的一个应用程序就是一个进程,每一个进程都是它自己的内存空间和系统资源

线程:

轻量级进程,在同一个进程内会有1个活多个线程,是大多数操作系统进行时序调度的基本单元

管程:

  • Monitor 其实是一种同步机制,他的义务是保证(同一时间) 只有一个线程可以访问被保护的数据和代码。
  • JVM 中同步都是基于进入和推出监视器对象(Monitor, 管程对象)来实现的,每个对象实例都会有一个 Monitor 对象。 
  • Monitor 对象会与 Java 对象一同创建并销毁,它底层是由 C++ 语言来实现的。
public class TreadDemo {public static void main(String[] args) {Object o = new Object();Thread thread = new Thread(()->{synchronized (o) {}}, "th2");thread.start();}
}

用户线程(User Thread):

  • 默认都是用户线程
  • 是系统的工作线程,它会完成这个程序需要完成的业务操作

守护线程(Daemon Thread):

  • 是一种特殊的线程为其他线程服务的,在后台默默地完成一些系统性的服务 比如垃圾回收线程
  • 守护线程作为一个服务线程,没有服务对象就没有必要继续运行了,如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可以推出了。所以加入当系统只剩下守护线程的时候,java 虚拟机会自动退出。

守护和用户代码演示:

import java.util.concurrent.TimeUnit;public class DaemonDemo {public static void main(String[] args) {Thread t1 = new Thread(()->{System.out.println(Thread.currentThread().getName() + "\\t 开始运行, " + (Thread.currentThread().isDaemon() ? "守护线程": "用户线程"));for (;;);}, "t1");// 需要在 start 之前,否则会报 IllegalThreadStateExceptiont1.setDaemon(true);t1.start();  try{TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "\\t -- end 主线程");}
}