public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println("MyThread.run()"); } }
3.2 Thread 类
1 2 3 4 5 6 7 8 9
public class MyThread extends Thread { public void run() { System.out.println("MyThread.run()"); } } MyThread myThread1 = new MyThread(); MyThread myThread2 = new MyThread(); myThread1.start(); myThread2.start();
3.3 Callable/Future 带返回值的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public class CallableDemo implements Callable<String> { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool (1); CallableDemo callableDemo = new CallableDemo(); Future<String> future = executorService.submit(callableDemo); System.out.println(future.get()); executorService.shutdown(); } @Override public String call() throws Exception { int a = 1; int b = 2; System.out.println(a + b); return "执行结果:" + (a + b); } }
public class Thread implements Runnable { /* Make sure registerNatives is the first thing <clinit> does. */ private static native void registerNatives(); static { registerNatives();//start0()方法是在此方法中注册的 }
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". */ 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 { start0();//实体调用的是这个方法,它是native的 started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } }
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) : Thread() #if INCLUDE_ALL_GCS , _satb_mark_queue(&_satb_mark_queue_set), _dirty_card_queue(&_dirty_card_queue_set) #endif // INCLUDE_ALL_GCS { if (TraceThreadEvents) { tty->print_cr("creating thread %p", this); } initialize(); _jni_attach_state = _not_attaching_via_jni; set_entry_point(entry_point); // Create the native thread itself. // %note runtime_23 os::ThreadType thr_type = os::java_thread; thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread : os::java_thread; os::create_thread(this, thr_type, stack_sz); _safepoint_visible = false; // The _osthread may be NULL here because we ran out of memory (too many threads active). // We need to throw and OutOfMemoryError - however we cannot do this here because the caller // may hold a lock and all locks must be unlocked before throwing the exception (throwing // the exception consists of creating the exception object & initializing it, initialization // will leave the VM via a JavaCall and then all locks must be unlocked). // // The thread is still suspended when we reach here. Thread must be explicit started // by creator! Furthermore, the thread must also explicitly be added to the Threads list // by calling Threads:add. The reason why this is not done here, is because the thread // object must be fully initialized (take a look at JVM_Start) }
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); } }
// The first routine called by a new Java thread void JavaThread::run() { // initialize thread-local alloc buffer related fields this->initialize_tlab();
// used to test validitity of stack trace backs this->record_base_of_stack_pointer();
// Record real stack base and size. this->record_stack_base_and_size();
// Initialize thread local storage; set before calling MutexLocker this->initialize_thread_local_storage();
this->create_stack_guard_pages();
this->cache_global_variables();
// Thread is now sufficient initialized to be handled by the safepoint code as being // in the VM. Change thread state from _thread_new to _thread_in_vm ThreadStateTransition::transition_and_fence(this, _thread_new, _thread_in_vm);
// This operation might block. We call that after all safepoint checks for a new thread has // been completed. this->set_active_handles(JNIHandleBlock::allocate_block());
if (JvmtiExport::should_post_thread_life()) { JvmtiExport::post_thread_start(this); }
EventThreadStart event; if (event.should_commit()) { event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj())); event.commit(); }
// We call another function to do the rest so we are sure that the stack addresses used // from there will be lower than the stack base just computed thread_main_inner();
// Note, thread is no longer valid at this point! }
public void interrupt() { if (this != Thread.currentThread()) checkAccess();
synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); // Just to set the interrupt flag b.interrupt(this); return; } } interrupt0(); }
// Ensure that the C++ Thread and OSThread structures aren't freed before we operate oop java_thread = JNIHandles::resolve_non_null(jthread); MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); // We need to re-resolve the java_thread, since a GC might have happened during the // acquire of the lock JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); if (thr != NULL) { Thread::interrupt(thr); } JVM_END
void os::interrupt(Thread* thread) { assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); //获取本地线程对象 OSThread* osthread = thread->osthread(); //判断本地线程是否为中断 if (!osthread->interrupted()) { //设置中断状态为true osthread->set_interrupted(true); // More than one thread can get here with the same value of osthread, // resulting in multiple notifications. We do, however, want the store // to interrupted() to be visible to other threads before we execute unpark(). //内存屏障的目的是使得interrupted状态对其他线程立即可见 OrderAccess::fence(); //_SleepEvent相当于Thread.sleep,表示如果线程调用了sleep方法,则通过unpark唤醒 ParkEvent * const slp = thread->_SleepEvent ; if (slp != NULL) slp->unpark() ; }
// For JSR166. Unpark even if interrupt status already was set if (thread->is_Java_thread()) ((JavaThread*)thread)->parker()->unpark(); //_ParkEvent用于synchronized同步块和Object.wait(),这里相当于也是通过unpark进行唤醒 ParkEvent * ev = thread->_ParkEvent ; if (ev != NULL) ev->unpark() ;