-
Java如何获取当前线程
2018-07-05 08:26:48Java 中经常会遇到要获取当前线程的情况,这时一般我们就会通过Thread.currentThread()来获取,接下去就看看执行该语句在 JVM 中做了什么吧。 简单例子 以下是一个简单的例子,获取当前线程并打印线程名称,输出...前言
Java 中经常会遇到要获取当前线程的情况,这时一般我们就会通过
Thread.currentThread()
来获取,接下去就看看执行该语句在 JVM 中做了什么吧。简单例子
以下是一个简单的例子,获取当前线程并打印线程名称,输出是”main”,即主线程。
public class CurrentThreadTest { public static void main(String[] args) { Thread t = Thread.currentThread(); System.out.println(t.getName()); } }
currentThread方法
在 Thread 类中,
currentThread
是一个静态且本地方法。public static native Thread currentThread();
Thread.c
Java 层声明的本地方法对应实现在 Thread.c 中,
currentThread
是一个注册到 JVM 中的方法,它与 JVM 中的JVM_CurrentThread
函数绑定了,所以实现逻辑在JVM_CurrentThread
函数里。逻辑为:
*JVMWrapper("JVM_CurrentThread")
用于调试。
* 通过thread->threadObj()
获取 oop,这里的 thread 是在JNI_ENTRY
宏中获取到的,详细情况可参考后面的JNI_ENTRY
和JNI_END
宏。
* 调用JNIHandles::make_local
函数#define THD "Ljava/lang/Thread;" static JNINativeMethod methods[] = { ... {"currentThread", "()" THD, (void *)&JVM_CurrentThread}, ... }; JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) JVMWrapper("JVM_CurrentThread"); oop jthread = thread->threadObj(); assert (thread != NULL, "no current thread!"); return JNIHandles::make_local(env, jthread); JVM_END
make_local
函数中主要看thread_from_jni_environment
函数,它用于获取当前线程,它的逻辑为JavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset()));
,即直接通过地址偏移来做减法计算得到JavaThread*
,这是因为 JavaThread 对象包含了 JNIEnv 对象属性,所以可以通过JNIEnv*
与偏移做减法来算出JavaThread*
。最后还要检查线程是否已经终止状态,没有终止才返回该线程对象。获取到
JavaThread*
对象后,分配句柄并将 oop 赋给句柄,并且转成 Java 层的对象 jobject。jobject JNIHandles::make_local(JNIEnv* env, oop obj) { if (obj == NULL) { return NULL; } else { JavaThread* thread = JavaThread::thread_from_jni_environment(env); assert(Universe::heap()->is_in_reserved(obj), "sanity check"); return thread->active_handles()->allocate_handle(obj); } } static JavaThread* thread_from_jni_environment(JNIEnv* env) { JavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset())); if (thread_from_jni_env->is_terminated()) { thread_from_jni_env->block_if_vm_exited(); return NULL; } else { return thread_from_jni_env; } }
JNI_ENTRY
和JNI_END
宏这两个宏将共同的部分都抽离出来了。其中
JNI_END
比较简单,就两个结束大括号。#define JNI_ENTRY(result_type, header) JNI_ENTRY_NO_PRESERVE(result_type, header) WeakPreserveExceptionMark __wem(thread); #define JNI_END } }
JNI_ENTRY
主要逻辑:
* 获取当前执行线程 JavaThread 指针对象。
* 创建 ThreadInVMfromNative 对象。
* TRACE_CALL ,这里什么都不干。
* 创建 HandleMarkCleaner 对象。
* 将 thread 赋值给 Exceptions 中的 THREAD。
* 校验栈对齐。
* 创建 WeakPreserveExceptionMark 对象。#define JNI_ENTRY_NO_PRESERVE(result_type, header) \ extern "C" { \ result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ ThreadInVMfromNative __tiv(thread); \ debug_only(VMNativeEntryWrapper __vew;) \ VM_ENTRY_BASE(result_type, header, thread) #define VM_ENTRY_BASE(result_type, header, thread) \ TRACE_CALL(result_type, header) \ HandleMarkCleaner __hm(thread); \ Thread* THREAD = thread; \ os::verify_stack_alignment();
————-推荐阅读————
跟我交流,向我提问:
公众号的菜单已分为“读书总结”、“分布式”、“机器学习”、“深度学习”、“NLP”、“Java深度”、“Java并发核心”、“JDK源码”、“Tomcat内核”等,可能有一款适合你的胃口。
欢迎关注:
-
如何中断当前线程
2017-11-10 16:39:37如何中断当前线程中断当前线程有两种方式。第一种方式是通过调用线程的stop()方法,第二种方式通过调用interrupt()方法。 由于第一种方式是不安全的,所以本篇文章不做讨论,主要分享一下如何使用interrupt()方法来...如何中断当前线程
中断当前线程有两种方式。第一种方式是通过调用线程的stop()方法,第二种方式通过调用interrupt()方法。
由于第一种方式是不安全的,所以本篇文章不做讨论,主要分享一下如何使用interrupt()方法来中断线程。采用interrupt中止线程
Thread类中提供了三个中断线程的方法,如下图:
方法详情:- interrupt():中断当前线程。该方法仅设置当前线程的状态为中断,实际上并不中断线程的运行。如果要中断线程的运行,还需要当前线程自己中断
- interrupted():测试当前线程的状态是否被中断。使用这个方法会清除当前线程的状态。简言之,如果这个方法被调用了两次,那么第二次会返回false. 除非当前线程在第二次调用之前,第一次清除线程状态之后,再次再中断。
- isInterrupted():测试当前线程的状态是否被中断。这个方法与interrupted()这个方法最大的差异是isInterrupted()方法不会清除当前线程的状态。
代码示例
public class ThreadInterruptDemo implements Runnable { @Override public void run() { // System.out.println("第一次调用Thread.interrupted()" + Thread.interrupted()); // System.out.println("第二次调用Thread.interrupted()" + Thread.interrupted()); /** * isInterrupted() * 用来测试当前线程的运行状态 * true:表示当前线程为中断状态 * false:表示当前线程为运行状态 * 可以通过这样的方法来中断线程运行 */ if (Thread.currentThread().isInterrupted()){ System.out.println("由于线程状态是中断,所以return不再执行线程任务"); return; } while (true) { try { Thread.sleep(3L); System.out.println("线程正在执行"); } catch (InterruptedException e) { e.printStackTrace(); break; } } } public static void main(String[] args) { Thread thread = new Thread(new ThreadInterruptDemo(), "ThreadInterruptDemo"); // 开启线程 thread.start(); /** * 中断当前线程 * 该方法仅设置当前线程的状态为中断,实际上并不中断线程的运行 * 如果要中断线程的运行,还需要当前线程自己中断 */ thread.interrupt(); } }
源代码链接:
https://github.com/myNameIssls/javase-study/blob/master/javase-multithreading/src/main/java/cn/tyrone/javase/thread/ThreadInterruptDemo.java
参考链接:
https://docs.oracle.com/javase/8/docs/api/
https://www.cnblogs.com/w-wfy/p/6414801.html
http://blog.csdn.net/paincupid/article/details/47626819 -
Java多线程-41-获取当前线程对象和线程休眠
2018-08-30 23:21:51这篇学习关于Thread类的两个方法,第一个是获取当前线程对象,返回的是一个Thread对象。第二个方法是我们自动化中经常使用的,线程休眠。 1.currentThread() 获取的是当前线程对象,是对象不是对象名称,如果要...这篇学习关于Thread类的两个方法,第一个是获取当前线程对象,返回的是一个Thread对象。第二个方法是我们自动化中经常使用的,线程休眠。
1.currentThread()
获取的是当前线程对象,是对象不是对象名称,如果要获取名称,需要对象.getName()实现。
package thread; public class Demo5_Thread { public static void main(String[] args) { new Thread() { public void run() { System.out.println(this.getName() +": aaaaa"); } }.start(); new Thread(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+": bbbb"); } }).start(); //main方法打印线程名称 System.out.println(Thread.currentThread().getName()); } }
运行结果:
Thread-0: aaaaa main Thread-1: bbbb
这个打印结果,也说明了,多线程中,main方法本身就是一个单独线程执行,而且执行顺序并不会像代码写的从上往下的顺序。
2.线程休眠
休眠就是让线程停顿下来,支持不同时间单位的中断。这个方法是Thread.sleep(xxx毫秒)。我们写自动化脚本经常需要用到它。
package thread; public class Demo5_Thread { public static void main(String[] args) throws InterruptedException { new Thread() { public void run() { for(int i = 0; i< 10; i ++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.getName() +": aaaaa"); } } }.start(); new Thread(new Runnable() { public void run() { for(int i = 0; i< 10; i ++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+": bbbb"); } } }).start(); //main方法打印线程名称 System.out.println(Thread.currentThread().getName()); } }
运行之后,可以看到间隔一秒输出一个。
-
QT获取当前线程ID
2019-09-25 09:01:43QT获取当前线程ID 用QSerialPort串口类的时候出现了: [WARNING ] QObject: Cannot create children for a parent that is in a different thread. (Parent is QSerialPort(0x505f250), parent’s thread is QThread...QT获取当前线程ID
用QSerialPort串口类的时候出现了:
[WARNING ] QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0x505f250), parent’s thread is QThread(0x2b7ff0), current thread is QThread(0x563a860)
于是想要输出一下到底现在是在哪个线程里跑,不废话,直接上代码:QString LogInfo; LogInfo.sprintf("%p", QThread::currentThread()); qDebug() << "OpenSerialPort " <<"threadID : "<<LogInfo;
-
C#中如何判断当前线程是否为主线程
2016-11-25 16:44:21转自:C#中如何判断当前线程是否为主线程 / Do this when you start your application static int mainThreadId; // In Main method: mainThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId... -
Linux最大线程数限制及当前线程数查询
2018-10-29 11:27:46Linux最大线程数限制及当前线程数查询 1、总结系统限制有: /proc/sys/kernel/pid_max #查系统支持的最大线程数,一般会很大,相当于理论值 /proc/sys/kernel/thread-max max_user_process(ulimit -u) #系统... -
Java多线程-当前线程副本:ThreadLocal
2016-06-16 20:27:53一般情况我们创建的变量是可以被任何一个线程访问并修改的,而使用ThreadLocal创建的变量只能被当前线程访问,其他线程无法访问和修改。 ThreadLocal<T> 接口的方法也很简单,只有四个方法: public class ... -
使当前线程暂停的方法
2019-07-08 15:25:44/*使当前线程暂停的方法 Thread类下: * public static void sleep(long millis) 使当前正在运行的进程暂停millis毫秒 * */ public class Demo03 { public static void main(String[] args) { for ... -
如何判断当前线程是主线程
2018-09-05 23:04:14在iOS中如何准确判断当前线程是主线程 -
eclipse 调试之停止当前线程
2018-07-31 14:59:21在eclipse中调试java的时候,如果不想继续走下一步了, 可以采取直接抛出异常的方式直接停止当前线程 需要打开display窗口 然后直接运行这个,就会抛出异常,然后这个线程就会被停止了... -
.net C# 中 thread 开启线程之后获取当前线程的信息
2016-07-06 17:05:42public static void XXX(object param) { Thread th = Thread.CurrentThread;//获取当前工作的线程 th.Abort();//强制关闭当前线程 } -
java获得当前线程的名称
2017-12-19 18:06:22//获得当前线程的名称 System.out.println(Thread.currentThread().getName()); -
Windows 下 GoLang 获取当前线程ID
2019-07-16 17:07:00Windows 下 GoLang 获取当前线程ID func GetCurrentThreadId() int { var user32 *syscall.DLL var GetCurrentThreadId *syscall.Proc var err error user32, err = syscall.LoadDLL("Kernel32.dll")... -
C++11当前线程this_thread实战
2019-04-13 08:30:02C++11提供了一个命名空间this_thread来引用当前线程,该命名空间有4个有用的函数,get_id,yield,sleep_until,sleep_for。 get_id是用来获取线程ID的。 其他3个函数都和时间相关,下面分别进行实战演练。 二yield... -
线程 NSThread 多线程 获取当前线程
2014-02-21 18:55:19线程 NSThread 多线程 线程与进程 进程 是一个活动的程序,一个容器 是系统资源管理的最小单位 切换代价较高 线程 是在进程容器中运行,实际工作的代码 是程序执行的最小单位 切换代价较低(由于线程是在同一块内存... -
下面那些情况可以终止当前线程的运行 java程序输出结果
2020-04-15 21:20:52当一个优先级高的线程进入就绪状态时,当前线程执行时,如果是抢占式的调度方式,是会暂停当前线程的执行的,当仍然不是终止它的执行。当不是抢占式的调度时,高优先级的线程将在当前线程终止后,得到优先的执行权。... -
java多线程基础(4)-调度方式之暂停当前线程方式3-线程休眠(sleep)
2016-07-07 15:02:32休眠是与放弃yield相比是更有力的放弃方式, 放弃只是表示当前线程愿意暂停当前线程,让其他有相同优先级的等待线程有机会获得cpu资源。而进入休眠sleep不同,不管有没有其他线程在等待资源,都进入暂停,这样一来... -
Windows/Linux下获取当前线程的ID号
2018-09-17 20:07:00在多线程场合,为了方便跟踪线程的运行状态,往往需要在程序中添加打印当前线程ID号的功能。 1. Linux下打印当前线程ID pthread_t pthread_self() 2. Windows下打印当前线程ID DWORD GetCurrentThreadId(); ... -
java入门--- 线程操作实例之获取当前线程名称
2018-06-05 10:53:28以下实例演示了如何通过继承 Thread 类并使用 getName() 方法来获取当前线程名称:public class TwoThreadGetName extends Thread { public void run() { for (int i = 0; i < 10; i++) { printMsg(); }... -
Looper判断当前线程是否是主线程
2017-08-22 12:11:201.判断方法可以借助Looper来判断当前线程是否是主线程:代码:public boolean isMainThread() { return Looper.getMainLooper() == Looper.myLooper(); }getMainLooper()得到的是整个application的主线程。myLooper... -
Windows核心编程读书笔记4——线程(4)当前线程句柄与伪句柄
2015-02-10 09:57:22在windows编程中,有时候我们会遇到需要传入作用对象句柄的函数,如GetThreadTimes...GetCurrentThread()函数即可,其会返回当前线程的“伪”句柄。类似的,我们也有函数可以获得当前进程的句柄。 HANDLE GetCurrentTh -
Android 打印当前线程的调用堆栈
2017-11-15 15:20:55/** * 打印当前线程的调用堆栈 * */ public static void printTrack(){ StackTraceElement[] st = Thread.currentThread().getStackTrace(); if(st==null){ System.out.println -
判断当前线程是否UI线程
2017-11-20 11:23:08两种方法: 1.if (Thread.currentThread() == Looper.getMainLooper().getThread()) { // UI线程 } else { // 非UI线程 } 2.if (Looper.myLooper() == Looper.getM -
Java线程异常时,是否会把共享变量在当前线程计算结果回写主存
2016-05-27 10:22:57Java线程异常时,是否会把共享变量在当前线程计算结果回写主存。 在看内存模型时,说明每个线程从主存里拷贝变量到自己的工作内存里,然后进行计算,对于共享变量的操作实际都是操作自己工作内存里的。 然后会把... -
java-实时打印当前线程的调用堆栈
2017-04-26 09:47:54java-实时打印当前线程的调用堆栈 /** * 打印当前线程的调用堆栈 * */ void printTrack(){ StackTraceElement[] st = Thread.currentThread().getStackTrace(); if(st==null){ System.out.println("无堆栈...");... -
winform 使用webbrowser 报错:当前线程不在单线程单元中,因此无法实例化 ActiveX
2019-06-27 15:53:30在程序中调用窗体时,因另一个窗体包含webbrowser,因此在实例化时报错:当前线程不在单线程单元中,因此无法实例化 ActiveX,查找了下网上的一些方法,说的最多的是在入口添加[STAThread],但我一看项目本身默认创建... -
Android 如何判断当前线程是否是主线程
2016-03-28 09:49:09Android开发中, 有时需要判断当前线程到底是主线程, 还是子线程, 例如: 我们在自定义View时, 想要让View重绘, 需要先判断当前线程到底是不是主线程, 然后根据判断结果来决定到底是调用 invalidate() 还