
可以通过“ThreadcurrentThread()getStackTrace()”,来获得当前调用堆栈。从而获得所需要的调用类及方法。
package demo;public class Main {
public static void main(String[] args) {
//JFinalstart("webRoot", 8080, "/");
Main m = new Main();
ma1();
}
public void a1(){
new A()a();
}
}
class A{
public void a(){
new B()b();
}
}
class B{
public void b(){
new C()c();
}
}
class C{
public void c(){
StackTraceElement[] es = ThreadcurrentThread()getStackTrace();
for(StackTraceElement e : es){
Systemoutprintln(egetClassName());
}
}
}
运行结果:
对
于线程的控制,我们将介绍一个
Handler类,使用该类可以对运行在不同线程中的多个任务进行排队,并使用Message和Runnable对象安排这些任务。在javadoc中,
对Handler是这样解释的:Handler可以发送和处理消息对象或Runnable对象,这些消息对象和Runnable对象与一个线程相关联。每
个Handler的实例都关联了一个线程和线程的消息队列。当创建了一个Handler对象时,一个线程或消息队列同时也被创建,该Handler对象将
发送和处理这些消息或Runnable对象。
下面有几种对Handler对象的构造方法需要了解一下:
a、如果new一个无参构造函数的Handler对象,那么这个Handler将自动与当前运行线程相关联,也就是说这个Handler将与当前运行的线程使用同一个消息队列,并且可以处理该队列中的消息。
private Handler handler = new Handler();
我们做这样一个实验,在主用户界面中创建一个带有无参构造函数的Handler对象,该Handler对象向消息队列推送一个Runnable对象,
在Runnable对象的run函数中打印当前线程Id,我们比较主用户界面线程ID和Runnable线程ID是否相同。具体代码如下:
public class HandlerTest01 extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
superonCreate(savedInstanceState);
setContentView(Rlayoutmain);
Systemoutprintln("Activity ---> " + ThreadcurrentThread()getId());
handlerpost(r);
}
private Handler handler = new Handler();
private Runnable r = new Runnable() {
@Override
public void run() {
try {
Threadsleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
eprintStackTrace();
}
Systemoutprintln("Runnalbe ---> " + ThreadcurrentThread()getId());
}
};
}
通过这个例子的输出可以发现,Runnable对象和主用户界面线程的ID是相同。在这个例子中,我们直接利用handler对象post了一个
runnable对象,相当于直接调用了Runnable对象的run函数,也就说没有经过start函数调用run(),那么就不会创建一个新线程,而
是在原有线程内部直接调用 run()方法,因此输出的线程Id是相同的。
b、如果new一个带参构造函数的Handler对象,那么这个Handler对象将与参数所表示的Looper相关联。注意:此时线程类应该是一个特殊类HandlerThread类,一个Looper类的Thread类,它继承自Thread类。
HandlerThread handlerthread = new HandlerThread("MyThread");
handlerthreadstart();
private MyHandler handler = new MyHandler(handlerthreadgetLooper());
class MyHandler extends Handler {
public MyHandler() {
}
public MyHandler(Looper looper) {
super(looper);
}
}
下面这个例子,将介绍如何开启一个新的线程,并通过Handler处理消息。
public class HandlerTest02 extends Activity {
private MyHandler myhandler = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
superonCreate(savedInstanceState);
thissetContentView(Rlayoutmain);
Systemoutprintln("Activity ---> " + ThreadcurrentThread()getId());
// 生成一个HandlerThread对象,使用Looper来处理消息队列
HandlerThread thread = new HandlerThread("MyThread");
// 必须启动这个线程
threadstart();
// 将一个线程绑定到Handler对象上,则该Handler对象就可以处理线程的消息队列
myhandler = new MyHandler(threadgetLooper());
// 从Handler中获取消息对象
Message msg = myhandlerobtainMessage();
// 将msg对象发送给目标对象Handler
msgsendToTarget();
}
class MyHandler extends Handler {
public MyHandler() {
}
// 带有参数的构造函数
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Systemoutprintln("MyHandler ---> " + ThreadcurrentThread()getId());
}
}
}
根据这个例子返回的结果,可以看出,新线程Id与主用户界面的线程Id不同。由于我们调用了threadstart()方法,真正的创建了一个新线程,与原来的线程处于不同的线程上下文中,因此打印输出的线程Id是不同的。
c、如果需要Handler对象去处理消息,那么就要重载Handler类的handleMessage函数。
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO : Handle the msg
// Usually we update UI here
}
}
注意到注释部分,我们通常在handleMessage中处理更新UI界面的 *** 作。
前面介绍了Handler类的基本使用,但是还是没有涉及到Thread类。要想实现在后台重新开启一个新的线程,通过该线程执行一些费时的 *** 作,我们也使用Thread类来完成这个功能。下面我们先给出一个使用Thread类的例子程序。
public class ThreadTest extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
superonCreate(savedInstanceState);
thissetContentView(Rlayoutmain);
Systemoutprintln("Activity ---> " + ThreadcurrentThread()getId());
Thread thread = new Thread(r);
threadstart();
try {
ThreadcurrentThread()sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
eprintStackTrace();
}
threadstop();
}
Runnable r = new Runnable() {
@Override
public void run() {
Systemoutprintln("Runnable ---> " + ThreadcurrentThread()getId());
}
};
}
这个程序执行的结果如下。新线程在创建对象时,传入了Runnable类的一个对象,在Runnable对象中重载了run()方法去执行耗时的 *** 作;新的线程实例执行了start方法,开启了一个新的线程执行Runnable的run方法。
上面这些就是我现在接触到执行线程的方法,在线程中,可以完成我们所需要的 *** 作(比如:下载,处理数据,检测网络状态等),使其与UI界面分离,那么UI界面不会因为耗时 *** 作导致界面被阻塞。
在《解密Google
Android》一书中,发现了这样一个启动线程的模型。利用该模型,我们可以把一些耗时的 *** 作放到doStuff方法中去执行,同时在
updateUIHere方法中进行更新UI界面的 *** 作,就可以完成一个线程所需要的功能。其他的说明写在注释部分了。
Handler myHandler = new Handler() {
public void handleMessage(Message msg) {
updateUIHere();
}
}
new Thread() {
public void run() {
doStuff(); // 执行耗时 *** 作
Message msg = myHandlerobtainMessage();
Bundle b = new Bundle();
bputString("key", "value");
msetData(b); // 向消息中添加数据
myHandlersendMessage(m); // 向Handler发送消息,更新UI
}
}start();
======================================================================================================
通过上面的文章,可以对handler的处理机制有一个比较深刻的认识,而我之前的疑问,为什么在handler中post一个线程,也就有了答案。
handler的应用相当一个对多线程管理的机制,通过一个线程的队列(因为可以post多个)来管理这些线程,
同时通过使用Handler或者HandlerThread来控制,这些线程是要在主线程中执行还是要新开一个线程来执行。
另外一个不错的例子
参考网址:>
VS2010还没有实现C++11的线程支持库, 换VS2012或者VS2013
std::thread 的使用非常放便和强大,该类几乎可以把任何函数作为线程主函数。
用法:
首先包含头文件 #include <thread>
定义线程主函数: 根据不同的需要,线程的主函数可以是普通函数、函数对象、lambda表达式或者类成员函数。
建立std::thread对象,并把线程要运行的函数(线程主函数)以及相应的函数参数通过构造函数传递给该对象, 构造函数通常会海纳百川。
例:
#include <thread>#include <iostream>
class ThreadMain {
public:
void operator()() {
run();
}
void run() {
std::cout << "Hello, C++11 thread\n";
}
};
void generalFunc(int data) {
std::cout << "Hello, C++11 thread\n";
}
int main() {
ThreadMain tm;
std::thread t1(generalFunc, 1); /传递普通函数指针和参数0给thread对象t1/
std::thread t2(&ThreadMain::run, &tm); /将成员函数传递给thread对象t2, 并且传递调用该函数的对象的指针&tm/
std::thread t3(tm); /传递一个函数对象给t3/
std::thread t4([]() { std::cout << "Hello, C++11 thread\n"; }); /传递lambda表达式给thread对象t4/
/ 调用join函数等待线程终止,并回收线程所占资源/
t1join();
t2join();
t3join();
t4join();
}
swt执行线程
SWT中的多线程机制和awt/swing中有些不同,这个大家应该都知道,不过还是要说下,Display对象中负责调用其他线程的方法有以下3种:● asyncExec(Runnable runnable):异步启动新的线程。所谓异步就是,UI线程不会等待runnable对象执行结束后再继续进行,就是说UI线程可以和runnable对象所在的线程同时运行。● syncExec(Runnable runnable):同步启动新的线程。所谓同步就是,UI线程会等待runnable对象执行结束后才会继续进行,当runnable对象是耗时大的线程时,尽量不要采用此种方式。另外,对于该种方式创建的线程可通过getSyncThread()方法获得线程对象。● timerExec(int milliseconds,Runnable runnable):指定一段时间再启动新的线程。用此方法创建的线程,将会在指定的时间后再启动线程。当然用此方法创建的线程启动后,与UI线程是异步的。如果指定的时间为负数,将不会按时启动线程。另外Display对象中,与UI线程相关的方法如下所示:● 获得当前的UI线程对象的方法:getThread(),返回Thread对象。● 使UI线程处于休眠状态:sleep()。● 唤醒UI线程:wake()。上面几点都是书里面的原话,不做阐述了下面我要说的是一个写法的问题,不能小瞧啊,后果很严重如果有一个线程他要做的事需要很久比如5分钟,像我这样的初学swt的人一定是new了一个线程然后getDisplay()asyncExec(线程对象); 结果虽然执行成功,但是界面确处于挂起状态(假死),直到执行结束,不过要说的是的确是异步执行的,还是ui却不知道为什么停止用户响应,原理暂时先不去理了,swt源码太复杂了这里面就要引出一个问题为什么不 像下面这么写呢Thread thread = new Thread(线程对象);
threadstart();
因为swt中非UI线程中调用窗口控件如果不像上面三种写法那样写的话,会抛orgeclipseswtSWTException: Invalid thread access这个异常在swt中程序启动时只有一个主线程,在这里与awt和swing是不一样的,它不允许其他线程访问UI主线程中的部件,具读过swt源码的人说AsyncExec方法根本就没有新启动一个线程而是由Synchronizer调用其中的 run 方法而已如果是这样的话,也就难怪UI会挂起解决这个问题的一个比较好的方法是如果要异步执行的线程所做的工作非常少的话,就无所谓了,如果异步线程需要执行很长时间的话,应该像下面这样启动线程Thread thread = new Thread(线程对象);
threadstart();在线程对象里面所有调用到UI部件的地方classFindergetGui()getDisplay()syncExec(new Runnable() {
public void run() {
//do run
}
});历经几个小时问题终于解决了这里做个总结吧我对swt多线程的评价swt的syncExec ,asyncExec 以及timerExec都是伪线程执行方法,把它看成特别的Synchronizer调用就可以了,syncExec ,asyncExec 以及timerExec执行的线程要做的事只是改变UI部件的属性而已执行时间不能太长此外的其他 *** 作仍然由传统的线程来做这里要特别注意,swt执行线程只用于在传统线程中 *** 作ui组建在这里要感谢内部类,否则一个复杂的swt线程不知道要写多少个为swt部件服务的标准类
以上就是关于Java中被调用的类中的方法如何获得原调用的类的对象全部的内容,包括:Java中被调用的类中的方法如何获得原调用的类的对象、handler.post 为什么要将thread对象post到handler中执行、vs2010 如何使用c++11特性里面的thread等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)