- 浏览: 956040 次
- 性别:
- 来自: 魔都
文章分类
- 全部博客 (745)
- MultiThread (19)
- My Plan (118)
- JavaBasic (61)
- MyInterview (104)
- InternetTechnique (5)
- ProjectConclusion (1)
- Maven (5)
- MogoDb (5)
- Hadoop (11)
- Memcached (6)
- TechniqueCollect (1)
- Ibaits (1)
- Android (34)
- ItLife (40)
- Tree (2)
- ProjectArchitect (7)
- Open Source (3)
- liunx (5)
- socket (8)
- Spring (27)
- DesginPattern (35)
- WebBasic (13)
- English (13)
- structs (1)
- structs2 (2)
- Oracle (17)
- Hibernate (2)
- JavaScript (4)
- Jdbc (1)
- Jvm (15)
- Ibatis (1)
- DataStructures (13)
- Https/Socket/Tcp/Ip (3)
- Linux (4)
- Webservice (7)
- Io (2)
- Svn (1)
- Css (1)
- Ajax (1)
- ExtJs (1)
- UML (2)
- DataBase (6)
- BankTechnique (3)
- SpringMvc (3)
- Nio (3)
- Load Balancing/Cluster (3)
- Tools (1)
- javaPerformanceOptimization (8)
- Lucene(SEO) (1)
- My Think (80)
- NodeJs (1)
- Quartz (1)
- Distributed-java (1)
- MySql (7)
- Project (4)
- junit (4)
- framework (1)
- enCache (1)
- git (2)
- SCJP (1)
- sd (1)
最新评论
-
lkjxshi:
你都这水平了还考这个证干嘛
SCJP 认证考试指南 -
钟逸华:
问的真多
百度java开发面试题(转) -
zuimeitulip:
觉得我就是这样的,从小阅读量就很少,导致现在的读的速度非常慢, ...
让读书成为一种习惯 -
DDT_123456:
我觉得你是不符合要求。问你hashmap的那个问题,你那样回答 ...
阿里面试2(转) -
jingjing0907:
刚刚写了很多读过此博客的感受,竟然没有发上去,以为我注册账号还 ...
让读书成为一种习惯
线程之间的通讯可以有两种方法.
一.利用全局变量. 大家都可以访问,所以使用很方便.
二.利用PostThreadMesagge(ThreadId,Msg,0,0)来进行通讯.
其中要注意的问题是,因为利用CreateThread创建的线程是无消息获取通道,消息映射这些功能,只有有窗体的线程才具备这些功能,所以要自己获取消息队列,利用PeekMessage既可.
以下是我做的例子.
void CCTestDlg::OnBnClickedButtoncreatethread()
{
// TODO: Add your control notification handler code here
int by = sizeof(BYTE);
int a = sizeof(char);
int b = sizeof(short);
int c = sizeof(WORD);
int d = sizeof(int);
int e = sizeof(DWORD);
int f = sizeof(long);
int m =100;
int*p = &m;
int n=10;
const int* const pp = &n;
ABB ca(1,2,3);
ca.GetNum();
ABB dd(4,5,6);
dd.GetNum();
m_hWait1 = ::CreateEvent(0,TRUE,FALSE,0);
m_hWait2 = ::CreateEvent(0,TRUE,FALSE,0);
m_hWait3 = ::CreateEvent(0,TRUE,FALSE,0);
m_hWait4 = ::CreateEvent(0,TRUE,FALSE,0);
DWORD dwID;
HANDLE hHandle = ::CreateThread(NULL,0,ThreadProc,this,0,&dwID);
DWORD dwThread1,dwThread2;
HANDLE hThread1,hThread2;
m_pThread1 = new CThread1;
m_pThread2 = new CThread2;
hThread1 = ::CreateThread(NULL,0,CThread1::ThreadPoc,m_pThread1,0,&dwThread1);
hThread2 = ::CreateThread(NULL,0,CThread2::ThreadPoc,m_pThread2,0,&dwThread2);
if(hThread1)
{
m_Arry.Add(dwThread1);
m_pThread1->m_pMainWnd = this;
}
if(hThread2)
{
m_Arry.Add(dwThread2);
m_pThread2->m_pMainWnd = this;
}
}
CThread1::CThread1()
{
m_hStop = ::CreateEvent(0,true,false,0);
}
CThread1::~CThread1()
{
}
DWORD WINAPI CThread1::ThreadPoc(LPVOID lparam)
{
CThread1 *pThread1 = (CThread1*)lparam;
return pThread1->MainFunc();
}
DWORD CThread1::MainFunc()
{
while(::WaitForSingleObject(m_hStop, 10) != WAIT_OBJECT_0)//main loop
{
MSG msg;
if(PeekMessage(&msg , NULL, 0, 0, PM_REMOVE))
{
switch(msg.message)
{
case WM_THREAD_EXIT_MSG:
//
AfxMessageBox("Thread1 receive Thread2 exit");
break;
}
}
}
DWORD dwid = m_pMainWnd->m_Arry.GetAt(1);
PostThreadMessage(dwid,WM_THREAD_EXIT_MSG,0,0);
return 0;
}
void CThread1::StopServ()
{
SetEvent(m_hStop);
}
void CThread1::ThreadMsgFunction(WPARAM wParam,LPARAM lParam)
{
}
CThread2::CThread2()
{
m_hStop = ::CreateEvent(0,true,false,0);
}
CThread2::~CThread2()
{
}
DWORD WINAPI CThread2::ThreadPoc(LPVOID lparam)
{
CThread2 *pThread2 = (CThread2*)lparam;
return pThread2->MainFunc();
}
DWORD CThread2::MainFunc()
{
//while(::WaitForSingleObject(m_hStop,10)!=WAIT_OBJECT_0)
while(::WaitForSingleObject(m_hStop, 10) != WAIT_OBJECT_0)//main loop
{
MSG msg;
if(PeekMessage(&msg , NULL, 0, 0, PM_REMOVE))
{
switch(msg.message)
{
case WM_THREAD_EXIT_MSG:
//
AfxMessageBox("Thread2 receive Thread1 exit");
break;
}
}
}
DWORD dwid = m_pMainWnd->m_Arry.GetAt(0);
PostThreadMessage(dwid,WM_THREAD_EXIT_MSG,0,0);
return 0;
}
void CThread2::StopServ()
{
SetEvent(m_hStop);
}
void CThread2::ThreadMsgFunction(WPARAM wParam,LPARAM lParam)
{
}
void CCTestDlg::OnBnClickedButtonExitThread1()
{
// TODO: Add your control notification handler code here
m_pThread1->StopServ();
}
void CCTestDlg::OnBnClickedButtonExithread2()
{
// TODO: Add your control notification handler code here
m_pThread2->StopServ();
}
Java 线程应该注意的问题
2005.10.21 来自:网易科技 共有评论()条 发表评论 收藏
Java的线程编程非常简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注意的问题。
Java的线程编程非常简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注意的问题。
1.同步对象的恒定性All java objects are references.
对于局部变量和参数来说,java里面的int, float, double, boolean等基本数据类型,都在栈上。这些基本类型是无法同步的;java里面的对象(根对象是Object),全都在堆里,指向对象的reference在栈上。
java中的同步对象,实际上是对于reference所指的“对象地址”进行同步。
需要注意的问题是,千万不要对同步对象重新赋值。举个例子。
class A implements Runnable{
Object lock = new Object();
void run(){
for(...){
synchronized(lock){
// do something
...
lock = new Object(); } } } run函数里面的这段同步代码实际上是毫无意义的。因为每一次lock都给重新分配了新的对象的reference,每个线程都在新的reference同步。
大家可能觉得奇怪,怎么会举这么一个例子。因为我见过这样的代码,同步对象在其它的函数里被重新赋了新值。
这种问题很难查出来。
所以,一般应该把同步对象声明为final.
final Object lock = new Object();
使用Singleton Pattern 设计模式来获取同步对象,也是一种很好的选择。
2.如何放置共享数据实现线程,有两种方法,一种是继承Thread类,一种是实现Runnable接口。
上面举的例子,采用实现Runnable接口的方法。本文推荐这种方法。
首先,把需要共享的数据放在一个实现Runnable接口的类里面,然后,把这个类的实例传给多个Thread的构造方法。这样,新创建的多个Thread,都共同拥有一个Runnable实例,共享同一份数据。
如果采用继承Thread类的方法,就只好使用static静态成员了。如果共享的数据比较多,就需要大量的static静态成员,令程序数据结构混乱,难以扩展。这种情况应该尽量避免。
编写一段多线程代码,处理一个稍微复杂点的问题。两种方法的优劣,一试便知。
3.同步的粒度线程同步的粒度越小越好,即,线程同步的代码块越小越好。尽量避免用synchronized修饰符来声明方法。尽量使用synchronized(anObject)的方式,如果不想引入新的同步对象,使用synchronized(this)的方式。而且,synchronized代码块越小越好。
4.线程之间的通知这里使用“通知”这个词,而不用“通信”这个词,是为了避免词义的扩大化。
线程之间的通知,通过Object对象的wait()和notify() 或notifyAll() 方法实现。
下面用一个例子,来说明其工作原理:
假设有两个线程,A和B。共同拥有一个同步对象,lock。
1.首先,线程A通过synchronized(lock) 获得lock同步对象,然后调用lock.wait()函数,放弃lock同步对象,线程A停止运行,进入等待队列。
2.线程B通过synchronized(lock) 获得线程A放弃的lock同步对象,做完一定的处理,然后调用 lock.notify() 或者lock.notifyAll() 通知等待队列里面的线程A。
3.线程A从等待队列里面出来,进入ready队列,等待调度。
4.线程B继续处理,出了synchronized(lock)块之后,放弃lock同步对象。
5.线程A获得lock同步对象,继续运行。
例子代码如下:
public class SharedResource implements Runnable{
Object lock = new Object();
public void run(){
// 获取当前线程的名称。
String threadName = Thread.currentThread().getName();
if( “A”.equals(threadName)){
synchronized(lock){ //线程A通过synchronized(lock) 获得lock同步对象
try{
System.out.println(“ A gives up lock.”);
lock.wait(); // 调用lock.wait()函数,放弃lock同步对象,
// 线程A停止运行,进入等待队列。
}catch(InterruptedException e){ } // 线程A重新获得lock同步对象之后,继续运行。
System.out.println(“ A got lock again and continue to run.”);
} // end of synchronized(lock) } if( “B”.equals(threadName)){
synchronized(lock){//线程B通过synchronized(lock) 获得线程A放弃的lock同步对象
System.out.println(“B got lock.”);
lock.notify(); //通知等待队列里面的线程A,进入ready队列,等待调度。
//线程B继续处理,出了synchronized(lock)块之后,放弃lock同步对象。
System.out.println(“B gives up lock.”);
} // end of synchronized(lock)
boolean hasLock = Thread.holdsLock(lock); // 检查B是否拥有lock同步对象。
System.out.println(“B has lock ? -- ” hasLock); // false. } } } public class TestMain{
public static void main(){
Runnable resource = new SharedResource();
Thread A = new Thread(resource,”A”);
A.start();
// 强迫主线程停止运行,以便线程A开始运行。
try {
Thread.sleep(500);
}catch(InterruptedException e){ } Thread B = new Thread(resource,”B”);
B.start(); } }
5.跨类的同步对象对于简单的问题,可以把访问共享资源的同步代码都放在一个类里面。
但是对于复杂的问题,我们需要把问题分为几个部分来处理,需要几个不同的类来处理问题。这时,就需要在不同的类中,共享同步对象。比如,在生产者和消费者之间共享同步对象,在读者和写者之间共享同步对象。
如何在不同的类中,共享同步对象。有几种方法实现,
(1)前面讲过的方法,使用static静态成员,(或者使用Singleton Pattern.)
(2)用参数传递的方法,把同步对象传递给不同的类。
(3)利用字符串常量的“原子性”。
对于第三种方法,这里做一下解释。一般来说,程序代码中的字符串常量经过编译之后,都具有唯一性,即,内存中不会存在两份相同的字符串常量。
(通常情况下,C ,C语言程序编译之后,也具有同样的特性。)
比如,我们有如下代码。
String A = “atom”;
String B = “atom”;
我们有理由认为,A和B指向同一个字符串常量。即,A==B。
注意,声明字符串变量的代码,不符合上面的规则。
String C= new String(“atom”);
String D = new String(“atom”);
这里的C和D的声明是字符串变量的声明,所以,C != D。
有了上述的认识,我们就可以使用字符串常量作为同步对象。
比如我们在不同的类中,使用synchronized(“myLock”), “myLock”.wait(),“myLock”.notify(), 这样的代码,就能够实现不同类之间的线程同步。
本文并不强烈推荐这种用法,只是说明,有这样一种方法存在。
本文推荐第二种方法,(2)用参数传递的方法,把同步对象传递给不同的类。
关于java多线程一些心得 - Java综合 - Java - ITeye论坛(转载)
分类: JAVA 2011-06-29 17:08 86人阅读 评论(0) 收藏 举报
1、主线程死掉之后 ,所有在主线程上启动的线程并不会死掉
2、通过把线程加入ThreadGroup可以操作其他同组线程的生命
3、如果想在子线程中杀掉主线程,直接把主线程的Thread的传入子线程即可
4、要想关闭多线程程序,需要把当前所有的线程全部杀死才能关闭
5、各个线程互补影响~父子线程也不会有影响
千言万语汇总就那么几句话
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine continues to execute threads until either of the following occurs:
* The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
* All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
lirong1978
线程到底有啥用啊,不就是同时执行多个任务么,不就是CPU分配时间片一会儿执行这个,一会儿执行那个,跟先把这个执行完,再执行那个有什么区别啊,谁能说下呢
呵呵 有些程序是需要同时处理多个通道的....
c++一般采用多进程的方式~~直接fork
java的fork的话 会启动多个虚拟机进行执行~~所有采用多线程
多成成好像CPU利用率上面更好一些~~具体的就忘掉了
lirong1978 写道
线程到底有啥用啊,不就是同时执行多个任务么,不就是CPU分配时间片一会儿执行这个,一会儿执行那个,跟先把这个执行完,再执行那个有什么区别啊,谁能说下呢
因为并不是所有的线程都能很好的利用CPU,有可能有些操作会阻塞,如果顺序执行的话,那那个阻塞的方法岂不是拦着别的方法的执行,如果多线程的话,那个阻塞的方法只塞他自己的线程,别的线程照样跑。
经典的运用就是ServerSocket.accept(),一个线程一直等别人连接,另外可以起一些线程去处理连接到的socket,如果不用多线程,怎么处理的了?除非转换观念用NIO。
lirong1978 写道
线程到底有啥用啊,不就是同时执行多个任务么,不就是CPU分配时间片一会儿执行这个,一会儿执行那个,跟先把这个执行完,再执行那个有什么区别啊,谁能说下呢
你说的是并发,利用的单CPU轮询。现代意义的多线程是并行的,利用多CPU处理器,同时工作。
dyllove98 写道
呵呵 有些程序是需要同时处理多个通道的....
c++一般采用多进程的方式~~直接fork
java的fork的话 会启动多个虚拟机进行执行~~所有采用多线程
多成成好像CPU利用率上面更好一些~~具体的就忘掉了
JDK1.2 之前采用所谓的Green Thread,不完全依赖于OS的线程调度。
后面的版本就不同了,直接利用OS或者是CPU线程调度,值得一提的是,Java线程和OS线程的映射比率是M:N(可能一对一,当M=N时)。
借宝地问下。
setDeamon(boolean)
这个方法的具体作用是什么? 与no-Deamon有什么区别或者权限么?
至于为什么要多线程?
我记得书本上的解释是:当年进程切换太耗资源,系统需要保存现场,还需要内存寻址等等,而多线程共用进程资源,在进程内寻址,在做切换时容易得多,所以就有了多进程和多线程之分。
我觉得c++也应该提倡多线程而非多进程,而跟语言没关系。
另外在多CPU环境下,多线程才真正算个“多线程”,呵呵
setDeamon(boolean)用来设置线程为守护线程。
如果一个线程是守护线程,那么它创建的线程默认也是守护线程。
**不过我觉得你还是没有回答我的问题。
自己google了下:
Any Java thread can be a daemon thread. Daemon threads are service providers for other threads running in the same process as the daemon thread. The run() method for a daemon thread is typically an infinite loop that waits for a service request.
When the only remaining threads in a process are daemon threads, the interpreter exits. This makes sense because when only daemon threads remain, there is no other thread for which a daemon thread can provide a service.
做过实验才明白,原来当只存在Daemon线程且没有用户线程的时候,JVM退出,以前写thread的时候还真没注意,实验如下:
Java代码
public class DaemonThread extends Thread{
public void run(){
while(true){
System.out.println("I'm daemon");
}
}
public static void main(String args[]){
DaemonThread daemon=new DaemonThread();
daemon.setDaemon(true);
daemon.start();
}
}
[java] view plaincopy
public class DaemonThread extends Thread{
public void run(){
while(true){
System.out.println("I'm daemon");
}
}
public static void main(String args[]){
DaemonThread daemon=new DaemonThread();
daemon.setDaemon(true);
daemon.start();
}
}
可以看到JVM很快就退出了,虽然这里是一个while(true)循环。
**关于JVM的进程间通讯,没深入了解过,不妨说说?
至于Java多线程关于锁概念和进程间通讯,我觉得看了JVM的内存实现之后,大致就会明白了
小弟不才,线程间通讯这个话题,我了解也不是很多,个人觉得去baidu上搜一下经典的讲解才是王道。
不过我的一个简单理解是:Java的进程有自己的内存(比如有内存存放变量a),进程创建出来的各个线程也有自己的内存(如果线程用到变量a,那么线程有单独的内存存放变量a的一个copy)。
如果,线程同步变量a,那么线程第一次读取a的值的时候,就从进程内存中读取,否则从自己内存中读取。同理,如果线程同步变量a,每次写变量a的时候,不仅把值写入自己的内存中,也同时把值写入进程的内存中。
欢迎指正
zhaspe 写道
如果,线程同步变量a,那么线程第一次读取a的值的时候,就从进程内存中读取,否则从自己内存中读取。同理,如果线程同步变量a,每次写变量a的时候,不仅把值写入自己的内存中,也同时把值写入进程的内存中。
欢迎指正
你的意思是说,如果对共享资源变量a不做线程同步,那么各自的线程从自己内存中读?
这个显然与多线程读取共享资源,发生读脏数据的情形是矛盾的呀。
Java 线程应该注意的问题
2005.10.21 来自:网易科技 共有评论()条 发表评论 收藏
Java的线程编程非常简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注意的问题。
Java的线程编程非常简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注意的问题。
1.同步对象的恒定性All java objects are references.
对于局部变量和参数来说,java里面的int, float, double, boolean等基本数据类型,都在栈上。这些基本类型是无法同步的;java里面的对象(根对象是Object),全都在堆里,指向对象的reference在栈上。
java中的同步对象,实际上是对于reference所指的“对象地址”进行同步。
需要注意的问题是,千万不要对同步对象重新赋值。举个例子。
class A implements Runnable{
Object lock = new Object();
void run(){
for(...){
synchronized(lock){
// do something
...
lock = new Object(); } } } run函数里面的这段同步代码实际上是毫无意义的。因为每一次lock都给重新分配了新的对象的reference,每个线程都在新的reference同步。
大家可能觉得奇怪,怎么会举这么一个例子。因为我见过这样的代码,同步对象在其它的函数里被重新赋了新值。
这种问题很难查出来。
所以,一般应该把同步对象声明为final.
final Object lock = new Object();
使用Singleton Pattern 设计模式来获取同步对象,也是一种很好的选择。
2.如何放置共享数据实现线程,有两种方法,一种是继承Thread类,一种是实现Runnable接口。
上面举的例子,采用实现Runnable接口的方法。本文推荐这种方法。
首先,把需要共享的数据放在一个实现Runnable接口的类里面,然后,把这个类的实例传给多个Thread的构造方法。这样,新创建的多个Thread,都共同拥有一个Runnable实例,共享同一份数据。
如果采用继承Thread类的方法,就只好使用static静态成员了。如果共享的数据比较多,就需要大量的static静态成员,令程序数据结构混乱,难以扩展。这种情况应该尽量避免。
编写一段多线程代码,处理一个稍微复杂点的问题。两种方法的优劣,一试便知。
3.同步的粒度线程同步的粒度越小越好,即,线程同步的代码块越小越好。尽量避免用synchronized修饰符来声明方法。尽量使用synchronized(anObject)的方式,如果不想引入新的同步对象,使用synchronized(this)的方式。而且,synchronized代码块越小越好。
4.线程之间的通知这里使用“通知”这个词,而不用“通信”这个词,是为了避免词义的扩大化。
线程之间的通知,通过Object对象的wait()和notify() 或notifyAll() 方法实现。
下面用一个例子,来说明其工作原理:
假设有两个线程,A和B。共同拥有一个同步对象,lock。
1.首先,线程A通过synchronized(lock) 获得lock同步对象,然后调用lock.wait()函数,放弃lock同步对象,线程A停止运行,进入等待队列。
2.线程B通过synchronized(lock) 获得线程A放弃的lock同步对象,做完一定的处理,然后调用 lock.notify() 或者lock.notifyAll() 通知等待队列里面的线程A。
3.线程A从等待队列里面出来,进入ready队列,等待调度。
4.线程B继续处理,出了synchronized(lock)块之后,放弃lock同步对象。
5.线程A获得lock同步对象,继续运行。
例子代码如下:
public class SharedResource implements Runnable{
Object lock = new Object();
public void run(){
// 获取当前线程的名称。
String threadName = Thread.currentThread().getName();
if( “A”.equals(threadName)){
synchronized(lock){ //线程A通过synchronized(lock) 获得lock同步对象
try{
System.out.println(“ A gives up lock.”);
lock.wait(); // 调用lock.wait()函数,放弃lock同步对象,
// 线程A停止运行,进入等待队列。
}catch(InterruptedException e){ } // 线程A重新获得lock同步对象之后,继续运行。
System.out.println(“ A got lock again and continue to run.”);
} // end of synchronized(lock) } if( “B”.equals(threadName)){
synchronized(lock){//线程B通过synchronized(lock) 获得线程A放弃的lock同步对象
System.out.println(“B got lock.”);
lock.notify(); //通知等待队列里面的线程A,进入ready队列,等待调度。
//线程B继续处理,出了synchronized(lock)块之后,放弃lock同步对象。
System.out.println(“B gives up lock.”);
} // end of synchronized(lock)
boolean hasLock = Thread.holdsLock(lock); // 检查B是否拥有lock同步对象。
System.out.println(“B has lock ? -- ” hasLock); // false. } } } public class TestMain{
public static void main(){
Runnable resource = new SharedResource();
Thread A = new Thread(resource,”A”);
A.start();
// 强迫主线程停止运行,以便线程A开始运行。
try {
Thread.sleep(500);
}catch(InterruptedException e){ } Thread B = new Thread(resource,”B”);
B.start(); } }
5.跨类的同步对象对于简单的问题,可以把访问共享资源的同步代码都放在一个类里面。
但是对于复杂的问题,我们需要把问题分为几个部分来处理,需要几个不同的类来处理问题。这时,就需要在不同的类中,共享同步对象。比如,在生产者和消费者之间共享同步对象,在读者和写者之间共享同步对象。
如何在不同的类中,共享同步对象。有几种方法实现,
(1)前面讲过的方法,使用static静态成员,(或者使用Singleton Pattern.)
(2)用参数传递的方法,把同步对象传递给不同的类。
(3)利用字符串常量的“原子性”。
对于第三种方法,这里做一下解释。一般来说,程序代码中的字符串常量经过编译之后,都具有唯一性,即,内存中不会存在两份相同的字符串常量。
(通常情况下,C ,C语言程序编译之后,也具有同样的特性。)
比如,我们有如下代码。
String A = “atom”;
String B = “atom”;
我们有理由认为,A和B指向同一个字符串常量。即,A==B。
注意,声明字符串变量的代码,不符合上面的规则。
String C= new String(“atom”);
String D = new String(“atom”);
这里的C和D的声明是字符串变量的声明,所以,C != D。
有了上述的认识,我们就可以使用字符串常量作为同步对象。
比如我们在不同的类中,使用synchronized(“myLock”), “myLock”.wait(),“myLock”.notify(), 这样的代码,就能够实现不同类之间的线程同步。
本文并不强烈推荐这种用法,只是说明,有这样一种方法存在。
本文推荐第二种方法,(2)用参数传递的方法,把同步对象传递给不同的类。
一.利用全局变量. 大家都可以访问,所以使用很方便.
二.利用PostThreadMesagge(ThreadId,Msg,0,0)来进行通讯.
其中要注意的问题是,因为利用CreateThread创建的线程是无消息获取通道,消息映射这些功能,只有有窗体的线程才具备这些功能,所以要自己获取消息队列,利用PeekMessage既可.
以下是我做的例子.
void CCTestDlg::OnBnClickedButtoncreatethread()
{
// TODO: Add your control notification handler code here
int by = sizeof(BYTE);
int a = sizeof(char);
int b = sizeof(short);
int c = sizeof(WORD);
int d = sizeof(int);
int e = sizeof(DWORD);
int f = sizeof(long);
int m =100;
int*p = &m;
int n=10;
const int* const pp = &n;
ABB ca(1,2,3);
ca.GetNum();
ABB dd(4,5,6);
dd.GetNum();
m_hWait1 = ::CreateEvent(0,TRUE,FALSE,0);
m_hWait2 = ::CreateEvent(0,TRUE,FALSE,0);
m_hWait3 = ::CreateEvent(0,TRUE,FALSE,0);
m_hWait4 = ::CreateEvent(0,TRUE,FALSE,0);
DWORD dwID;
HANDLE hHandle = ::CreateThread(NULL,0,ThreadProc,this,0,&dwID);
DWORD dwThread1,dwThread2;
HANDLE hThread1,hThread2;
m_pThread1 = new CThread1;
m_pThread2 = new CThread2;
hThread1 = ::CreateThread(NULL,0,CThread1::ThreadPoc,m_pThread1,0,&dwThread1);
hThread2 = ::CreateThread(NULL,0,CThread2::ThreadPoc,m_pThread2,0,&dwThread2);
if(hThread1)
{
m_Arry.Add(dwThread1);
m_pThread1->m_pMainWnd = this;
}
if(hThread2)
{
m_Arry.Add(dwThread2);
m_pThread2->m_pMainWnd = this;
}
}
CThread1::CThread1()
{
m_hStop = ::CreateEvent(0,true,false,0);
}
CThread1::~CThread1()
{
}
DWORD WINAPI CThread1::ThreadPoc(LPVOID lparam)
{
CThread1 *pThread1 = (CThread1*)lparam;
return pThread1->MainFunc();
}
DWORD CThread1::MainFunc()
{
while(::WaitForSingleObject(m_hStop, 10) != WAIT_OBJECT_0)//main loop
{
MSG msg;
if(PeekMessage(&msg , NULL, 0, 0, PM_REMOVE))
{
switch(msg.message)
{
case WM_THREAD_EXIT_MSG:
//
AfxMessageBox("Thread1 receive Thread2 exit");
break;
}
}
}
DWORD dwid = m_pMainWnd->m_Arry.GetAt(1);
PostThreadMessage(dwid,WM_THREAD_EXIT_MSG,0,0);
return 0;
}
void CThread1::StopServ()
{
SetEvent(m_hStop);
}
void CThread1::ThreadMsgFunction(WPARAM wParam,LPARAM lParam)
{
}
CThread2::CThread2()
{
m_hStop = ::CreateEvent(0,true,false,0);
}
CThread2::~CThread2()
{
}
DWORD WINAPI CThread2::ThreadPoc(LPVOID lparam)
{
CThread2 *pThread2 = (CThread2*)lparam;
return pThread2->MainFunc();
}
DWORD CThread2::MainFunc()
{
//while(::WaitForSingleObject(m_hStop,10)!=WAIT_OBJECT_0)
while(::WaitForSingleObject(m_hStop, 10) != WAIT_OBJECT_0)//main loop
{
MSG msg;
if(PeekMessage(&msg , NULL, 0, 0, PM_REMOVE))
{
switch(msg.message)
{
case WM_THREAD_EXIT_MSG:
//
AfxMessageBox("Thread2 receive Thread1 exit");
break;
}
}
}
DWORD dwid = m_pMainWnd->m_Arry.GetAt(0);
PostThreadMessage(dwid,WM_THREAD_EXIT_MSG,0,0);
return 0;
}
void CThread2::StopServ()
{
SetEvent(m_hStop);
}
void CThread2::ThreadMsgFunction(WPARAM wParam,LPARAM lParam)
{
}
void CCTestDlg::OnBnClickedButtonExitThread1()
{
// TODO: Add your control notification handler code here
m_pThread1->StopServ();
}
void CCTestDlg::OnBnClickedButtonExithread2()
{
// TODO: Add your control notification handler code here
m_pThread2->StopServ();
}
Java 线程应该注意的问题
2005.10.21 来自:网易科技 共有评论()条 发表评论 收藏
Java的线程编程非常简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注意的问题。
Java的线程编程非常简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注意的问题。
1.同步对象的恒定性All java objects are references.
对于局部变量和参数来说,java里面的int, float, double, boolean等基本数据类型,都在栈上。这些基本类型是无法同步的;java里面的对象(根对象是Object),全都在堆里,指向对象的reference在栈上。
java中的同步对象,实际上是对于reference所指的“对象地址”进行同步。
需要注意的问题是,千万不要对同步对象重新赋值。举个例子。
class A implements Runnable{
Object lock = new Object();
void run(){
for(...){
synchronized(lock){
// do something
...
lock = new Object(); } } } run函数里面的这段同步代码实际上是毫无意义的。因为每一次lock都给重新分配了新的对象的reference,每个线程都在新的reference同步。
大家可能觉得奇怪,怎么会举这么一个例子。因为我见过这样的代码,同步对象在其它的函数里被重新赋了新值。
这种问题很难查出来。
所以,一般应该把同步对象声明为final.
final Object lock = new Object();
使用Singleton Pattern 设计模式来获取同步对象,也是一种很好的选择。
2.如何放置共享数据实现线程,有两种方法,一种是继承Thread类,一种是实现Runnable接口。
上面举的例子,采用实现Runnable接口的方法。本文推荐这种方法。
首先,把需要共享的数据放在一个实现Runnable接口的类里面,然后,把这个类的实例传给多个Thread的构造方法。这样,新创建的多个Thread,都共同拥有一个Runnable实例,共享同一份数据。
如果采用继承Thread类的方法,就只好使用static静态成员了。如果共享的数据比较多,就需要大量的static静态成员,令程序数据结构混乱,难以扩展。这种情况应该尽量避免。
编写一段多线程代码,处理一个稍微复杂点的问题。两种方法的优劣,一试便知。
3.同步的粒度线程同步的粒度越小越好,即,线程同步的代码块越小越好。尽量避免用synchronized修饰符来声明方法。尽量使用synchronized(anObject)的方式,如果不想引入新的同步对象,使用synchronized(this)的方式。而且,synchronized代码块越小越好。
4.线程之间的通知这里使用“通知”这个词,而不用“通信”这个词,是为了避免词义的扩大化。
线程之间的通知,通过Object对象的wait()和notify() 或notifyAll() 方法实现。
下面用一个例子,来说明其工作原理:
假设有两个线程,A和B。共同拥有一个同步对象,lock。
1.首先,线程A通过synchronized(lock) 获得lock同步对象,然后调用lock.wait()函数,放弃lock同步对象,线程A停止运行,进入等待队列。
2.线程B通过synchronized(lock) 获得线程A放弃的lock同步对象,做完一定的处理,然后调用 lock.notify() 或者lock.notifyAll() 通知等待队列里面的线程A。
3.线程A从等待队列里面出来,进入ready队列,等待调度。
4.线程B继续处理,出了synchronized(lock)块之后,放弃lock同步对象。
5.线程A获得lock同步对象,继续运行。
例子代码如下:
public class SharedResource implements Runnable{
Object lock = new Object();
public void run(){
// 获取当前线程的名称。
String threadName = Thread.currentThread().getName();
if( “A”.equals(threadName)){
synchronized(lock){ //线程A通过synchronized(lock) 获得lock同步对象
try{
System.out.println(“ A gives up lock.”);
lock.wait(); // 调用lock.wait()函数,放弃lock同步对象,
// 线程A停止运行,进入等待队列。
}catch(InterruptedException e){ } // 线程A重新获得lock同步对象之后,继续运行。
System.out.println(“ A got lock again and continue to run.”);
} // end of synchronized(lock) } if( “B”.equals(threadName)){
synchronized(lock){//线程B通过synchronized(lock) 获得线程A放弃的lock同步对象
System.out.println(“B got lock.”);
lock.notify(); //通知等待队列里面的线程A,进入ready队列,等待调度。
//线程B继续处理,出了synchronized(lock)块之后,放弃lock同步对象。
System.out.println(“B gives up lock.”);
} // end of synchronized(lock)
boolean hasLock = Thread.holdsLock(lock); // 检查B是否拥有lock同步对象。
System.out.println(“B has lock ? -- ” hasLock); // false. } } } public class TestMain{
public static void main(){
Runnable resource = new SharedResource();
Thread A = new Thread(resource,”A”);
A.start();
// 强迫主线程停止运行,以便线程A开始运行。
try {
Thread.sleep(500);
}catch(InterruptedException e){ } Thread B = new Thread(resource,”B”);
B.start(); } }
5.跨类的同步对象对于简单的问题,可以把访问共享资源的同步代码都放在一个类里面。
但是对于复杂的问题,我们需要把问题分为几个部分来处理,需要几个不同的类来处理问题。这时,就需要在不同的类中,共享同步对象。比如,在生产者和消费者之间共享同步对象,在读者和写者之间共享同步对象。
如何在不同的类中,共享同步对象。有几种方法实现,
(1)前面讲过的方法,使用static静态成员,(或者使用Singleton Pattern.)
(2)用参数传递的方法,把同步对象传递给不同的类。
(3)利用字符串常量的“原子性”。
对于第三种方法,这里做一下解释。一般来说,程序代码中的字符串常量经过编译之后,都具有唯一性,即,内存中不会存在两份相同的字符串常量。
(通常情况下,C ,C语言程序编译之后,也具有同样的特性。)
比如,我们有如下代码。
String A = “atom”;
String B = “atom”;
我们有理由认为,A和B指向同一个字符串常量。即,A==B。
注意,声明字符串变量的代码,不符合上面的规则。
String C= new String(“atom”);
String D = new String(“atom”);
这里的C和D的声明是字符串变量的声明,所以,C != D。
有了上述的认识,我们就可以使用字符串常量作为同步对象。
比如我们在不同的类中,使用synchronized(“myLock”), “myLock”.wait(),“myLock”.notify(), 这样的代码,就能够实现不同类之间的线程同步。
本文并不强烈推荐这种用法,只是说明,有这样一种方法存在。
本文推荐第二种方法,(2)用参数传递的方法,把同步对象传递给不同的类。
关于java多线程一些心得 - Java综合 - Java - ITeye论坛(转载)
分类: JAVA 2011-06-29 17:08 86人阅读 评论(0) 收藏 举报
1、主线程死掉之后 ,所有在主线程上启动的线程并不会死掉
2、通过把线程加入ThreadGroup可以操作其他同组线程的生命
3、如果想在子线程中杀掉主线程,直接把主线程的Thread的传入子线程即可
4、要想关闭多线程程序,需要把当前所有的线程全部杀死才能关闭
5、各个线程互补影响~父子线程也不会有影响
千言万语汇总就那么几句话
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine continues to execute threads until either of the following occurs:
* The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
* All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
lirong1978
线程到底有啥用啊,不就是同时执行多个任务么,不就是CPU分配时间片一会儿执行这个,一会儿执行那个,跟先把这个执行完,再执行那个有什么区别啊,谁能说下呢
呵呵 有些程序是需要同时处理多个通道的....
c++一般采用多进程的方式~~直接fork
java的fork的话 会启动多个虚拟机进行执行~~所有采用多线程
多成成好像CPU利用率上面更好一些~~具体的就忘掉了
lirong1978 写道
线程到底有啥用啊,不就是同时执行多个任务么,不就是CPU分配时间片一会儿执行这个,一会儿执行那个,跟先把这个执行完,再执行那个有什么区别啊,谁能说下呢
因为并不是所有的线程都能很好的利用CPU,有可能有些操作会阻塞,如果顺序执行的话,那那个阻塞的方法岂不是拦着别的方法的执行,如果多线程的话,那个阻塞的方法只塞他自己的线程,别的线程照样跑。
经典的运用就是ServerSocket.accept(),一个线程一直等别人连接,另外可以起一些线程去处理连接到的socket,如果不用多线程,怎么处理的了?除非转换观念用NIO。
lirong1978 写道
线程到底有啥用啊,不就是同时执行多个任务么,不就是CPU分配时间片一会儿执行这个,一会儿执行那个,跟先把这个执行完,再执行那个有什么区别啊,谁能说下呢
你说的是并发,利用的单CPU轮询。现代意义的多线程是并行的,利用多CPU处理器,同时工作。
dyllove98 写道
呵呵 有些程序是需要同时处理多个通道的....
c++一般采用多进程的方式~~直接fork
java的fork的话 会启动多个虚拟机进行执行~~所有采用多线程
多成成好像CPU利用率上面更好一些~~具体的就忘掉了
JDK1.2 之前采用所谓的Green Thread,不完全依赖于OS的线程调度。
后面的版本就不同了,直接利用OS或者是CPU线程调度,值得一提的是,Java线程和OS线程的映射比率是M:N(可能一对一,当M=N时)。
借宝地问下。
setDeamon(boolean)
这个方法的具体作用是什么? 与no-Deamon有什么区别或者权限么?
至于为什么要多线程?
我记得书本上的解释是:当年进程切换太耗资源,系统需要保存现场,还需要内存寻址等等,而多线程共用进程资源,在进程内寻址,在做切换时容易得多,所以就有了多进程和多线程之分。
我觉得c++也应该提倡多线程而非多进程,而跟语言没关系。
另外在多CPU环境下,多线程才真正算个“多线程”,呵呵
setDeamon(boolean)用来设置线程为守护线程。
如果一个线程是守护线程,那么它创建的线程默认也是守护线程。
**不过我觉得你还是没有回答我的问题。
自己google了下:
Any Java thread can be a daemon thread. Daemon threads are service providers for other threads running in the same process as the daemon thread. The run() method for a daemon thread is typically an infinite loop that waits for a service request.
When the only remaining threads in a process are daemon threads, the interpreter exits. This makes sense because when only daemon threads remain, there is no other thread for which a daemon thread can provide a service.
做过实验才明白,原来当只存在Daemon线程且没有用户线程的时候,JVM退出,以前写thread的时候还真没注意,实验如下:
Java代码
public class DaemonThread extends Thread{
public void run(){
while(true){
System.out.println("I'm daemon");
}
}
public static void main(String args[]){
DaemonThread daemon=new DaemonThread();
daemon.setDaemon(true);
daemon.start();
}
}
[java] view plaincopy
public class DaemonThread extends Thread{
public void run(){
while(true){
System.out.println("I'm daemon");
}
}
public static void main(String args[]){
DaemonThread daemon=new DaemonThread();
daemon.setDaemon(true);
daemon.start();
}
}
可以看到JVM很快就退出了,虽然这里是一个while(true)循环。
**关于JVM的进程间通讯,没深入了解过,不妨说说?
至于Java多线程关于锁概念和进程间通讯,我觉得看了JVM的内存实现之后,大致就会明白了
小弟不才,线程间通讯这个话题,我了解也不是很多,个人觉得去baidu上搜一下经典的讲解才是王道。
不过我的一个简单理解是:Java的进程有自己的内存(比如有内存存放变量a),进程创建出来的各个线程也有自己的内存(如果线程用到变量a,那么线程有单独的内存存放变量a的一个copy)。
如果,线程同步变量a,那么线程第一次读取a的值的时候,就从进程内存中读取,否则从自己内存中读取。同理,如果线程同步变量a,每次写变量a的时候,不仅把值写入自己的内存中,也同时把值写入进程的内存中。
欢迎指正
zhaspe 写道
如果,线程同步变量a,那么线程第一次读取a的值的时候,就从进程内存中读取,否则从自己内存中读取。同理,如果线程同步变量a,每次写变量a的时候,不仅把值写入自己的内存中,也同时把值写入进程的内存中。
欢迎指正
你的意思是说,如果对共享资源变量a不做线程同步,那么各自的线程从自己内存中读?
这个显然与多线程读取共享资源,发生读脏数据的情形是矛盾的呀。
Java 线程应该注意的问题
2005.10.21 来自:网易科技 共有评论()条 发表评论 收藏
Java的线程编程非常简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注意的问题。
Java的线程编程非常简单。但有时会看到一些关于线程的错误用法。下面列出一些应该注意的问题。
1.同步对象的恒定性All java objects are references.
对于局部变量和参数来说,java里面的int, float, double, boolean等基本数据类型,都在栈上。这些基本类型是无法同步的;java里面的对象(根对象是Object),全都在堆里,指向对象的reference在栈上。
java中的同步对象,实际上是对于reference所指的“对象地址”进行同步。
需要注意的问题是,千万不要对同步对象重新赋值。举个例子。
class A implements Runnable{
Object lock = new Object();
void run(){
for(...){
synchronized(lock){
// do something
...
lock = new Object(); } } } run函数里面的这段同步代码实际上是毫无意义的。因为每一次lock都给重新分配了新的对象的reference,每个线程都在新的reference同步。
大家可能觉得奇怪,怎么会举这么一个例子。因为我见过这样的代码,同步对象在其它的函数里被重新赋了新值。
这种问题很难查出来。
所以,一般应该把同步对象声明为final.
final Object lock = new Object();
使用Singleton Pattern 设计模式来获取同步对象,也是一种很好的选择。
2.如何放置共享数据实现线程,有两种方法,一种是继承Thread类,一种是实现Runnable接口。
上面举的例子,采用实现Runnable接口的方法。本文推荐这种方法。
首先,把需要共享的数据放在一个实现Runnable接口的类里面,然后,把这个类的实例传给多个Thread的构造方法。这样,新创建的多个Thread,都共同拥有一个Runnable实例,共享同一份数据。
如果采用继承Thread类的方法,就只好使用static静态成员了。如果共享的数据比较多,就需要大量的static静态成员,令程序数据结构混乱,难以扩展。这种情况应该尽量避免。
编写一段多线程代码,处理一个稍微复杂点的问题。两种方法的优劣,一试便知。
3.同步的粒度线程同步的粒度越小越好,即,线程同步的代码块越小越好。尽量避免用synchronized修饰符来声明方法。尽量使用synchronized(anObject)的方式,如果不想引入新的同步对象,使用synchronized(this)的方式。而且,synchronized代码块越小越好。
4.线程之间的通知这里使用“通知”这个词,而不用“通信”这个词,是为了避免词义的扩大化。
线程之间的通知,通过Object对象的wait()和notify() 或notifyAll() 方法实现。
下面用一个例子,来说明其工作原理:
假设有两个线程,A和B。共同拥有一个同步对象,lock。
1.首先,线程A通过synchronized(lock) 获得lock同步对象,然后调用lock.wait()函数,放弃lock同步对象,线程A停止运行,进入等待队列。
2.线程B通过synchronized(lock) 获得线程A放弃的lock同步对象,做完一定的处理,然后调用 lock.notify() 或者lock.notifyAll() 通知等待队列里面的线程A。
3.线程A从等待队列里面出来,进入ready队列,等待调度。
4.线程B继续处理,出了synchronized(lock)块之后,放弃lock同步对象。
5.线程A获得lock同步对象,继续运行。
例子代码如下:
public class SharedResource implements Runnable{
Object lock = new Object();
public void run(){
// 获取当前线程的名称。
String threadName = Thread.currentThread().getName();
if( “A”.equals(threadName)){
synchronized(lock){ //线程A通过synchronized(lock) 获得lock同步对象
try{
System.out.println(“ A gives up lock.”);
lock.wait(); // 调用lock.wait()函数,放弃lock同步对象,
// 线程A停止运行,进入等待队列。
}catch(InterruptedException e){ } // 线程A重新获得lock同步对象之后,继续运行。
System.out.println(“ A got lock again and continue to run.”);
} // end of synchronized(lock) } if( “B”.equals(threadName)){
synchronized(lock){//线程B通过synchronized(lock) 获得线程A放弃的lock同步对象
System.out.println(“B got lock.”);
lock.notify(); //通知等待队列里面的线程A,进入ready队列,等待调度。
//线程B继续处理,出了synchronized(lock)块之后,放弃lock同步对象。
System.out.println(“B gives up lock.”);
} // end of synchronized(lock)
boolean hasLock = Thread.holdsLock(lock); // 检查B是否拥有lock同步对象。
System.out.println(“B has lock ? -- ” hasLock); // false. } } } public class TestMain{
public static void main(){
Runnable resource = new SharedResource();
Thread A = new Thread(resource,”A”);
A.start();
// 强迫主线程停止运行,以便线程A开始运行。
try {
Thread.sleep(500);
}catch(InterruptedException e){ } Thread B = new Thread(resource,”B”);
B.start(); } }
5.跨类的同步对象对于简单的问题,可以把访问共享资源的同步代码都放在一个类里面。
但是对于复杂的问题,我们需要把问题分为几个部分来处理,需要几个不同的类来处理问题。这时,就需要在不同的类中,共享同步对象。比如,在生产者和消费者之间共享同步对象,在读者和写者之间共享同步对象。
如何在不同的类中,共享同步对象。有几种方法实现,
(1)前面讲过的方法,使用static静态成员,(或者使用Singleton Pattern.)
(2)用参数传递的方法,把同步对象传递给不同的类。
(3)利用字符串常量的“原子性”。
对于第三种方法,这里做一下解释。一般来说,程序代码中的字符串常量经过编译之后,都具有唯一性,即,内存中不会存在两份相同的字符串常量。
(通常情况下,C ,C语言程序编译之后,也具有同样的特性。)
比如,我们有如下代码。
String A = “atom”;
String B = “atom”;
我们有理由认为,A和B指向同一个字符串常量。即,A==B。
注意,声明字符串变量的代码,不符合上面的规则。
String C= new String(“atom”);
String D = new String(“atom”);
这里的C和D的声明是字符串变量的声明,所以,C != D。
有了上述的认识,我们就可以使用字符串常量作为同步对象。
比如我们在不同的类中,使用synchronized(“myLock”), “myLock”.wait(),“myLock”.notify(), 这样的代码,就能够实现不同类之间的线程同步。
本文并不强烈推荐这种用法,只是说明,有这样一种方法存在。
本文推荐第二种方法,(2)用参数传递的方法,把同步对象传递给不同的类。
发表评论
-
子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。
2013-04-15 14:00 1274public class ThreadTest { ... -
java并发包(java.util.concurrent)
2013-03-26 23:46 2023java并发包(java.util.concurrent) ... -
java 死锁及解决
2013-03-19 22:54 962url:http://leowzy.iteye.com/bl ... -
断点续传的原理
2013-03-08 12:32 1175url:http://www.cnblogs.com/Kil ... -
《java并发编程实践》读书笔记
2012-08-21 23:07 1009文章链接:http://www.iteye.com/blogs ... -
ThreadLocal详解
2012-06-27 23:47 963文章链接: http://www.iteye.com/top ... -
多线程并发(java编程思想笔记)
2012-06-25 23:50 24641.Executor,java.util.concurr ... -
多线程例题(空中网)
2012-06-17 19:16 1030文章链接:http://blog.csdn ... -
ArrayBlockingQueue(阻塞队列)
2012-06-17 19:00 1574package cn.itcast.day3.thread; ... -
多线程笔记(黑马)
2012-06-17 18:59 10281.多线程范围内间的线 ... -
设计缓冲系统(多线程)
2012-06-17 18:57 1054package cn.itcast.day3.thread; ... -
Java多线程与并发库高级应用(传智播客)
2012-06-13 15:14 3763------------------------------- ... -
多线程断点续传下载
2012-06-05 20:58 1798package cn.itcast.net.downlo ... -
java多线程断点续传
2012-06-05 10:00 1352在android下面的断点 ... -
多线程高新(黑马程序员)
2012-03-30 16:23 1236------------------------------- ... -
生产者/消费者JAVA多线程
2012-03-28 09:58 1065文章链接:http://blog.csdn.net/bnuch ... -
主线程跟子线程怎么通讯 java
2012-03-17 19:24 4636学到多线程,编了一个简单地电脑城进出货模拟系统。 代码有点长 ... -
理解多线程
2011-09-27 17:40 878一、理解多线程 多 ...
相关推荐
然而,由于线程之间的数据同步问题,直接在子线程修改主线程的数据可能会导致数据不一致或程序崩溃。本文将深入探讨如何安全、有效地在子线程中更新主线程的数据。 首先,理解线程安全。线程安全是指当多个线程访问...
子线程与主线程之间的通信方式有很多种,如使用共享变量、wait/notify机制、Future和Callable接口等。而观察者模式(Observer Pattern)则是一种设计模式,它允许一个对象的状态变化自动通知其他依赖该对象的对象。...
在 Java 中,存在两种线程模型:主线程和子线程。主线程是程序的入口点,而子线程是由主线程创建的辅助线程。子线程的运行结果可以通过阻塞的方式来获取。在 Java 中,我们可以使用 Callable 或 Runnable 接口来实现...
总的来说,Java提供了丰富的多线程同步机制,可以根据实际需求选择合适的方法来实现“主线程等待所有子线程完成再继续”的功能。在并发编程中,理解并灵活运用这些工具对于提高程序效率和避免死锁等问题至关重要。
Java 主线程等待子线程执行完毕 Java 中的多线程编程是非常重要的一部分,特别是在需要并发执行多个任务的情况下。然而,在某些情况下,我们需要等待所有子线程执行完毕后再继续执行主线程的剩余动作。这时,我们...
JAVA 主线程等待子线程执行完毕再执行 JAVA 中的线程控制是非常重要的一部分,而在实际开发中,我们经常会遇到需要主线程等待子线程执行完毕再执行的情况。这种情况下,我们可以使用两种方式来实现:主动式和被动式...
然而,当这些子线程需要与主线程交互,例如更新UI或共享数据时,就需要进行线程间通信。 Android提供了多种实现子线程间通信的方式: 1. **Handler-Message机制**:这是最常用的一种方式,通过创建Handler对象,一...
通过上述步骤,你可以实现Android主线程与子线程之间的有效通信。在实际开发中,`Handler`常常与`AsyncTask`、`IntentService`、`Runnable`等结合使用,构建复杂的异步处理逻辑。`MyHandler2`可能是这个示例中的具体...
在Android应用开发中,UI线程(也称为主线程)负责处理用户交互和绘制界面,而子线程通常用于执行耗时操作,如网络请求、数据处理等。由于Android系统的安全机制,直接在子线程中修改UI是不允许的,因此我们需要通过...
### Java多线程--让主线程等待所有子线程执行完毕 #### 核心知识点解析 在Java多线程环境中,让主线程等待所有子线程执行完毕是一个常见的需求,尤其是在处理大量数据或进行高性能计算时。这不仅有助于正确测量...
主线程如何捕获子线程的异常---马克-to-win java视频的介绍
在多线程编程中,子线程与主线程的交互是一个常见的需求,特别是在GUI应用程序中。主线程通常负责用户界面的更新和事件处理,而子线程则用于执行耗时的任务,以避免阻塞UI。本示例将深入探讨如何在Java或C#等支持多...
自己学着编写的一个JAVA多线程程序,该程序实现的功能是:在主线程main中创建两个子线程,A和B,线程A先运行,再运行B线程,当两个子线程都运行完毕后,才运行主线程,并最终结束整个程序的运行。 希望该程序对初学...
在Android开发中,多线程通信是一个至关重要的概念,尤其是主线程(UI线程)与子线程之间的交互。本文将深入探讨如何使用Handler机制实现主线程与子线程,以及HandlerThread之间的双向通信。 首先,理解Android的...
总的来说,主线程控制子线程的`wait()`和`notify()`操作是Java并发编程中的高级技巧,它允许我们构建更复杂、更高效的应用程序,通过线程间的协作来解决问题。理解和掌握这些概念对于编写高并发、高性能的Java应用...
"主线程等待子多线程(无结果返回)执行完成再继续执行"这个主题就涉及到如何在Java、C#、Python等编程语言中实现这种同步机制。下面将详细讨论这个知识点。 **1. Java中的`Thread.join()`方法** 在Java中,主线程...
例如,如果有多个子线程,我们可以在每个子线程执行`join()`,这样主线程会依次等待每个子线程完成。例如: ```java Thread thread1 = new Thread(...); Thread thread2 = new Thread(...); thread1.start(); ...
标题中的内容涉及到多线程编程,具体是一种交替执行的任务模式,即子线程循环10次,然后主线程循环100次,这样的交替过程重复50次。这是一个典型的线程交互场景,常用于实现并发任务,比如在GUI应用中更新界面或者在...
在Android应用开发中,线程间的交互是必不可少的,尤其是子线程与主线程之间的通信。主线程,也称为UI线程,负责处理用户界面的更新和事件响应,而子线程通常用于执行耗时操作,如网络请求、数据处理等,以避免阻塞...
本篇文章将深入探讨如何在Python中实现多线程,并让主线程等待所有子线程结束。 首先,我们需要了解Python中的`threading`模块,它是Python标准库中用于处理多线程的模块。在示例代码中,我们创建了两个函数`a()`和...