子线程唤醒主线程
- 格式:docx
- 大小:14.82 KB
- 文档页数:6
⼦线程任务发⽣异常时主线程事务回滚⽰例过程⽬录⼀、提出问题⼆、主线程与⼦线程三、线程池四、异常的捕获五、事务的回滚⼀、提出问题最近有⼀位朋友问了我这样⼀个问题,问题的截图如下:这个问题问的相对⽐较笼统,我来稍微详细的描述下:主线程向线程池提交了⼀个任务,如果执⾏这个任务过程中发⽣了异常,如何让主线程捕获到该异常并且进⾏事务的回滚。
⼆、主线程与⼦线程先来看看基础,下图体现了两种线程的运⾏⽅式,左侧的图,体现了主线程启动⼀个⼦线程之后,⼆者互不⼲扰独⽴运⾏,⽣死有命,从此你我是路⼈!右侧的图,体现了主线程启动⼀个⼦线程之后继续执⾏主线程程序逻辑,在某⼀节点通过阻塞的⽅式来获取⼦线程的执⾏结果。
对于上⽂中提出的问题,⼀定是第⼆种才能解决主线程能够捕获⼦线程执⾏过程中发⽣的异常。
这⾥就不得不提⼀个⾯试题,实现线程的两个接⼝Callable 与Runnable 之间的区别:123public interface Callable<V> {V call() throws Exception;}12public interface Runnable {public abstract void run();}可以看到call ⽅法带返回值,run ⽅法没有返回值。
另外call ⽅法可以抛出异常,run ⽅法不可以。
很明显,我们为了要捕获或得知⼦线程的运⾏结果,或者运⾏异常,都应该通过Callable 接⼝来实现。
这⾥我们写⼀个ExpSubThread 类(⼦线程异常模拟类),实现Callable 接⼝,不做过多的动作,直接抛出⼀个空指针异常。
12345public class ExpSubThread implements Callable { @Override publicObject call() throws Exception {throw new NullPointerException();}}三、线程池在⾯临线程任务时,通常我们会预先建⽴⼀个线程池,线程池是预先规划好的n 个线程资源的集合。
近年来,随着互联网和移动互联网的快速发展,Java作为一种广泛应用的编程语言,其在多线程编程领域的应用日益普及。
在多线程编程中,经常会遇到在线程中调用主线程的方法的需求,这是一个具有挑战性的问题。
在本文中,我将深入探讨如何在Java的多线程编程中实现在子线程中调用主线程的方法,以及其中涉及的深度和广度的知识和技巧。
1. 多线程编程的基本概念在开始探讨在Java中如何在子线程中调用主线程方法之前,首先需要对多线程编程的基本概念有一个清晰的了解。
多线程编程是指在一个程序中同时运行多个线程,每个线程执行不同的任务。
在Java中,可以通过继承Thread类或实现Runnable接口来创建和启动线程。
多线程编程能够充分利用多核处理器的并行计算能力,提高程序的运行效率。
2. 子线程调用主线程方法的挑战在Java的多线程编程中,每个线程都有自己的独立执行流程,无法直接调用其他线程的方法。
要实现在子线程中调用主线程的方法是一项具有挑战性的任务。
通常情况下,我们需要借助一些技巧和机制来实现这一目标。
3. 使用SwingUtilities.invokeLater()实现跨线程调用在Java的图形用户界面编程中,经常会遇到在子线程中更新UI界面的需求。
此时,可以使用SwingUtilities.invokeLater()方法来实现在子线程中调用主线程的方法。
该方法可以将指定的Runnable对象放到事件队列中,由事件分发线程按顺序执行。
通过这种方式,可以实现在子线程中更新UI界面的效果。
4. 使用Callable和Future实现异步任务除了SwingUtilities.invokeLater()方法外,还可以使用Callable和Future来实现在子线程中调用主线程的方法。
Callable接口类似于Runnable接口,但是可以返回执行结果或抛出异常。
Future接口则表示异步计算的结果,提供了检查计算是否完成、等待计算完成并获取结果的方法。
Chapter26首先查看相关汇编指令的含义:选项含义:26.1答:首先查看loop.s文件内容如下:运行以上命令,得到以下结果:使用“-c”选项运行命令查看答案,结果和上图一致,说明分析正确。
26.2答:分析以上命令可知“-t2”表示指定两个线程,“-i100”表示中断间隔为100,“-a dx=3,dx=3”表示指定线程0和线程1的dx均初始化为3,运行以上命令得以下运行结果:使用“-c”选项运行命令查看答案,结果和上图一致,说明分析正确。
26.3答:分析以上命令可知,相对第二题,该命令只是将中断间隔由原来的100改为3,运行以上命令得到以下运行结果:(此结果为-s为0)使用“-c”选项运行命令查看答案,结果和上图一致,说明分析正确。
再对“-s”的值进行改变和运行,查看结果可知不同的种子情况下运行结果一致。
由本实验可知中断频率会改变程序的行为。
26.4答:首先查看并分析looping-race-nolock.s文件的内容如下图:运行以上命令得到以下结果:使用“-c”选项运行命令查看答案,结果和上图一致,说明分析正确。
Chapter28首先查看选项明确含义,大多数的选项与Chapter26的相同,主要有以下新选项:28.1答:首先查看flag.s文件内容:运行命令得以下结果:由上图可知,首先是线程0获得锁,直到执行结束释放锁之后线程1才获得锁并执行。
由此可分析以上汇编代码是想通过用一个变量来标志锁是否被某些线程占用。
第一个线程到达时首先会检查标志是否为0,如果是0则设置标志为1表示已经获得锁,其他线程到达时如果第一个线程仍未执行结束则一直检查标志是否为0,直到第一个线程执行结束释放锁(将标志设置为0)才会被其他线程获取。
28.2答:有第一题可得,使用默认值运行时,flag.s可按预期工作。
可以产生正确的结果,并且可以预测代码运行时最终的flag标志会被置0,因为线程1执行结束后锁会被释放。
使用-M和-R对相应的地址内存和寄存器进行跟踪,运行一下命令“./x86.py-p flag.s-R ax,bx-M flag,count-c”,运行结果如下图:28.3答:在第二题的命令的基础上加上-a选项“-a bx=2,bx=2”再次运行,结果如下。
信号量wait用法信号量是用来控制多线程并发执行的一种同步机制,常用的操作包括wait和signal。
wait是用来阻塞线程的操作,它可以设置一个初始值,当初始值小于等于0时,线程会被阻塞;当初始值大于0时,线程可以继续执行。
在使用wait时,通常会有两种情况:1.等待资源释放:当一个线程需要一个特定的资源,但该资源正在其他线程使用时,线程可以调用wait来等待资源释放。
例如,多个线程需要访问一个共享变量,但只能有一个线程访问该变量,其他线程需要等待,当该线程访问完之后调用signal来唤醒其他线程。
2.等待某个条件满足:当一个线程需要某个条件满足才能继续执行时,可以使用wait来等待条件的满足。
例如,一个线程需要等待某个标志位变为真时才能执行后续操作,可以调用wait来等待标志位变为真,当条件满足时,再调用signal来唤醒线程。
在使用wait时,需要注意以下几点:1. wait操作必须在synchronized块内进行,以确保在调用wait之前线程获得锁,否则会抛出IllegalMonitorStateE某ception异常。
2. wait操作会释放线程持有的锁,使得其他线程可以获得锁并执行。
3. 调用wait会使得线程进入等待状态,直到被其他线程唤醒。
可以使用signal或signalAll来唤醒线程,唤醒的线程将会重新竞争获取锁。
4. 在调用wait之前,通常需要判断某个条件是否满足,如果条件已经满足,则不需要等待,可以直接执行后续操作。
否则,调用wait进行等待。
5. wait可以设置超时时间,如果超过指定的时间仍未被唤醒,则会自动唤醒线程。
6. 如果有多个线程在等待同一个资源或条件的话,可以使用notifyAll来唤醒所有等待的线程,而不是只唤醒一个线程。
总结来说,信号量的wait操作是一种线程等待的机制,在需要等待某个资源释放或某个条件满足时使用。
它可以让线程进入等待状态,并释放持有的锁,以允许其他线程获得锁并执行。
C#中Invoke的⽤法()-解决⼦线程访问主线程控件、线程安全等问题⼀直对invoke和begininvoke的使⽤和概念⽐较混乱,这两天看了些资料,对这两个的⽤法和原理有了些新的认识和理解。
⾸先说下,invoke和begininvoke的使⽤有两种情况:1. control中的invoke、begininvoke。
2. delegrate中的invoke、begininvoke。
这两种情况是不同的,我们这⾥要讲的是第1种。
下⾯我们在来说下.NET中对invoke和begininvoke的官⽅定义。
control.invoke(参数delegate)⽅法:在拥有此控件的基础窗⼝句柄的线程上执⾏指定的委托。
control.begininvoke(参数delegate)⽅法:在创建控件的基础句柄所在线程上异步执⾏指定委托。
根据这两个概念我们⼤致理解invoke表是同步、begininvoke表⽰异步。
但是如何来进⾏同步和异步呢?我们来做⼀个测试。
invoke 例⼦:private void button1_Click(object sender, EventArgs e){MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"AAA");invokeThread = new Thread(new ThreadStart(StartMethod));invokeThread.Start();string a = string.Empty;for (int i = 0; i < 3; i++) //调整循环次数,看的会更清楚{Thread.Sleep(1000);a = a + "B";}MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+a);}private void StartMethod(){MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"CCC");button1.Invoke(new invokeDelegate(invokeMethod));MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"DDD");}private void invokeMethod(){//Thread.Sleep(3000);MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString() + "EEE");}结论:我们运⾏后,看下程序的运⾏顺序,1AAA->3CCC和1BBB->1EEE ->3DDD 。
c 主线程子线程用法主题:主线程和子线程的用法引言:在计算机科学中,线程是操作系统能够进行运算调度的最小单位,用于实现并发执行。
在多线程编程中,主线程和子线程是常被提及的概念。
主线程是程序的入口点,也是最重要的执行线程,而子线程在主线程启动后创建,用于执行辅助任务。
本文将逐步介绍主线程和子线程的用法,并探讨它们在并发编程中的重要性。
第一部分:什么是主线程1.1 主线程的概念主线程是程序的默认线程,也是整个程序的入口点。
它负责程序的初始化、创建子线程以及处理用户交互等任务。
1.2 主线程的特点主线程是唯一的,程序必须要有一个主线程。
它负责创建和管理其他线程,并且在其他线程执行完毕后结束。
第二部分:什么是子线程2.1 子线程的概念子线程是在主线程启动后创建的其他线程,用于执行一些辅助任务,如计算、网络请求等。
2.2 子线程的特点子线程可以并发执行,与主线程相互独立,互不干扰。
子线程的创建由主线程负责,可以根据需要创建多个子线程。
第三部分:主线程和子线程的用法3.1 主线程的用法- 初始化:主线程负责进行程序的初始化工作,如加载配置文件、初始化全局变量等。
- 处理用户交互:主线程接收用户的输入,并根据用户的操控来执行相应的逻辑。
- 创建子线程:主线程可以根据需要创建子线程,并分配任务给子线程执行。
- 结束程序:主线程在所有子线程执行完毕后,负责结束整个程序。
3.2 子线程的用法- 计算密集型任务:子线程适用于执行一些耗时的计算任务,如图像处理、数据分析等。
- 网络请求:在网络编程中,子线程常被用来执行网络请求任务,以免阻塞主线程。
- UI更新:在某些情况下,子线程可以用于更新UI,例如加载大量图片时,可以使用子线程来执行图片加载任务,提高用户体验。
第四部分:主线程与子线程的协作4.1 线程同步当多个线程需要共享资源时,为了避免竞争条件和数据不一致问题,需要进行线程同步。
常见的线程同步机制包括互斥锁、条件变量等。
java await方法Java中的await()方法是一个非常重要的线程同步工具,它可以让一个线程等待其他线程的完成,从而实现多个线程之间的协调与同步。
在本文中,我们将详细介绍Java中await()方法的使用方法和注意事项。
一、什么是await()方法await()方法是Java中Object类提供的一个用于线程同步的方法,它可以让一个线程等待其他线程执行完毕后再继续执行。
具体来说,当一个线程调用某个对象的await()方法时,它会被阻塞,并释放该对象上的锁,直到其他线程调用该对象上的notify()或notifyAll()方法唤醒它。
二、await()方法的使用1. 使用方式在Java中,我们可以通过以下方式来使用await()方法:```public synchronized void await(long timeout) throwsInterruptedException {if (timeout <= 0L) {while (!isSignalled)wait();} else {long deadline = System.nanoTime() + timeout;while (!isSignalled && deadline > System.nanoTime()) { TimeUnit.NANOSECONDS.timedWait(this, deadline - System.nanoTime());}}}```其中,timeout表示等待时间(单位为毫秒),isSignalled表示是否已经被唤醒。
如果timeout为0,则表示一直等待;否则,在指定时间内未被唤醒,则会自动返回。
2. 示例代码下面是一个简单的示例代码,演示了如何使用await()方法实现线程同步:```public class AwaitExample {private final Object lock = new Object();private boolean isSignalled = false;public void doWait() throws InterruptedException { synchronized (lock) {while (!isSignalled) {lock.wait();}isSignalled = false;}}public void doNotify() {synchronized (lock) {isSignalled = true;lock.notify();}}}```在这个示例中,我们定义了一个AwaitExample类,其中包含了两个方法:doWait()和doNotify()。
唤醒线程的方法唤醒线程是多线程编程中的一个重要概念。
在多线程编程中,线程可以被休眠或者阻塞,唤醒线程就是将处于休眠或者阻塞状态的线程重新转化为就绪状态的过程,下面介绍一些常用的唤醒线程的方法。
一、使用wait和notify方法唤醒线程wait和notify方法是Java中的线程同步关键字,可以用于唤醒线程。
wait方法可以使当前线程进入等待状态,并释放对象锁;notify方法可以唤醒正在等待对象锁的线程,使其进入就绪状态。
wait和notify方法必须在同步代码块中使用,因为在同步代码块中可以使用对象锁。
示例代码:synchronized (obj) {obj.wait();}synchronized (obj) {obj.notify();}二、使用join方法唤醒线程join方法的作用是等待调用该方法的线程结束,然后才继续运行当前线程。
使用join方法可以保证调用join方法的线程会在被调用线程结束后才会被唤醒,进入就绪状态。
示例代码:Thread thread=new Thread(new MyRunnable());thread.start();thread.join();三、使用Lock和Condition唤醒线程Lock和Condition是Java中的并发包,其中Lock用于替换同步代码块,在使用Condition之前需要先获得Lock。
Condition是一种线程通信机制,可以通过await方法使线程进入等待状态,通过signal方法唤醒等待线程。
示例代码:Lock lock=new ReentrantLock();Condition condition=lock.newCondition();lock.lock();try{condition.await();}catch(Exception e){e.printStackTrace();}finally{lock.unlock();}lock.lock();try{condition.signal();}catch(Exception e){e.printStackTrace();}finally{lock.unlock();}总结:通过以上示例代码,我们了解了唤醒线程的三种常用方法,包括使用wait和notify方法、使用join方法和使用Lock和Condition实现线程唤醒。
一、介绍在Java中,线程的等待是指一个线程暂时停止执行以等待某个条件的触发。
线程的等待通常与锁相关联,当线程等待时,它会释放持有的锁,从而允许其他线程进入临界区。
Java提供了多种方法让线程进入等待状态,本文将为您详细介绍这些方法。
二、w本人t()方法w本人t()方法是Object类中的一个实例方法,它使当前线程进入等待状态,直到其他线程调用notify()或notifyAll()方法唤醒它。
w本人t()方法必须在同步块或同步方法中调用,否则会抛出IllegalMonitorStateException异常。
w本人t()方法也可以指定等待的时间,超过指定时间后线程会自动唤醒。
三、join()方法join()方法是Thread类中的一个实例方法,它使当前线程等待指定线程执行完毕。
当调用join()方法时,当前线程会进入等待状态,直到指定线程执行完毕才会继续执行。
四、sleep()方法sleep()方法是Thread类中的一个静态方法,它使当前线程进入休眠状态,指定的时间过后再重新唤醒。
sleep()方法不会释放锁,因此其他线程无法访问该线程的同步块或同步方法。
五、park()方法park()方法是LockSupport类中的一个静态方法,它使当前线程进入等待状态,直到其他线程调用unpark()方法唤醒它。
与w本人t()方法不同,park()方法不需要在同步块或同步方法中调用。
六、aw本人t()方法aw本人t()方法是Condition接口中的一个实例方法,它使当前线程进入等待状态,直到其他线程调用signal()或signalAll()方法唤醒它。
与w本人t()方法类似,aw本人t()方法必须在Lock对象的控制下调用。
七、总结通过本文的介绍,我们详细了解了Java中让线程进入等待的方法,包括w本人t()、join()、sleep()、park()和aw本人t()等方法。
这些方法各有特点,可以根据实际需求选择合适的方法来实现线程的等待。
java多线程学习基础篇(三)Thread类的常⽤⽅法线程Thread是⼀个程序的多个执⾏路径,执⾏调度的单位,依托于进程存在。
线程不仅可以共享进程的内存,⽽且还拥有⼀个属于⾃⼰的内存空间,这段内存空间也叫做线程栈,是在建⽴线程时由系统分配的,主要⽤来保存线程内部所使⽤的数据,如线程执⾏函数中所定义的变量。
Java中的多线程是⼀种抢占机制⽽不是分时机制。
抢占机制指的是有多个线程处于可运⾏状态,但是只允许⼀个线程在运⾏,他们通过竞争的⽅式抢占CPU。
下⾯介绍⼀些常⽤的Thread⽅法。
Thread.join():静态⽅法,返回对当前正在执⾏的线程对象的引⽤在很多情况下,主线程⽣成并起动了⼦线程,如果⼦线程⾥要进⾏⼤量的耗时的运算,主线程往往将于⼦线程之前结束,但是如果主线程处理完其他的事务后,需要⽤到⼦线程的处理结果,也就是主线程需要等待⼦线程执⾏完成之后再结束,这个时候就要⽤到join()⽅法了。
Join⽅法实现是通过wait(⼩提⽰:Object 提供的⽅法)。
当main线程调⽤t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调⽤该对象的wait(等待时间),直到该对象唤醒main线程,⽐如退出后。
这就意味着main 线程调⽤t.join时,必须能够拿到线程t对象的锁。
join() ⼀共有三个重载版本,分别是⽆参、⼀个参数、两个参数:public final void join() throws InterruptedException; //⽆参数的join()等价于join(0),作⽤是⼀直等待该线程死亡public final synchronized void join(long millis) throws InterruptedException; //最多等待该线程死亡millis毫秒public final synchronized void join(long millis, int nanos) throws InterruptedException; //最多等待该线程死亡millis毫秒加nanos纳秒(1) 三个⽅法都被final修饰,⽆法被⼦类重写。
子线程唤醒主线程朋友让我帮忙写个程序从文本文档中导入数据到oracle 数据库中,技术上没有什么难度,文档的格式都是固定的只要对应数据库中的字段解析就行了,关键在于性能。
数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis()在最后一个子进程结束后记录当前时间,两次一减得到的时间差即为总共的用时,代码如下Java代码收藏代码long tStart = System.currentTimeMillis();System.out.println(Thread.currentThread().getName() + "开始");//打印开始标记for (int ii = 0; ii < threadNum; ii++) {//开threadNum个线程Runnable r = new Runnable(){@Overridepublic void run(){System.out.println(Thread.currentThread().getName() + "开始");//做一些事情... ...System.out.println(Thread.currentThread().getName() + "结束.");}}Thread t = new Thread(r);t.start();}System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记long tEnd = System.currentTimeMillis();System.out.println("总共用时:"+ (tEnd - tStart) + "millions");结果是几乎在for循环结束的瞬间就执行了主线程打印总共用时的语句,原因是所有的子线程是并发执行的,它们运行时主线程也在运行,这就引出了一个问题即本文标题如何"让主线程等待所有子线程执行完毕"。
试过在每个子线程开始后加上t.join(),结果是所有线程都顺序执行,这就失去了并发的意义了,显然不是我想要的。
网上Google了很久也没有找到解决方案,难道就没有人遇到过这种需求吗?还是这个问题太简单了?无耐只得自己想办法了...最后我的解决办法是,自定义一个ImportThread类继承自ng.Thread,重载run()方法,用一个List属性保存所有产生的线程,这样只要判断这个List是否为空就知道还有没有子线程没有执行完了,类代码如下:Java代码收藏代码public class ImportThread extends Thread {private static List<Thread> runningThreads = new ArrayList<Thread>(); public ImportThread() {}@Overridepublic void run() {regist(this);//线程开始时注册System.out.println(Thread.currentThread().getName() + "开始...");//打印开始标记//做一些事情... ...unRegist(this);//线程结束时取消注册System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记}public void regist(Thread t){synchronized(runningThreads){runningThreads.add(t);}}public void unRegist(Thread t){synchronized(runningThreads){runningThreads.remove(t);}}public static boolean hasThreadRunning() {return (runningThreads.size() > 0);//通过判断runningThreads是否为空就能知道是否还有线程未执行完}}主线程中代码:Java代码收藏代码long tStart = System.currentTimeMillis();System.out.println(Thread.currentThread().getName() + "开始");//打印开始标记for (int ii = 0; ii < threadNum; ii++) {//开threadNum个线程Thread t = new ImportThread();t.start();}while(true){//等待所有子线程执行完if(!ImportThread.hasThreadRunning()){break;}Thread.sleep(500);}System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记long tEnd = System.currentTimeMillis();System.out.println("总共用时:"+ (tEnd - tStart) + "millions");打印的结果是:main开始Thread-1开始...Thread-5开始...Thread-0开始...Thread-2开始...Thread-3开始...Thread-4开始...Thread-5结束.Thread-4结束.Thread-2结束.Thread-0结束.Thread-3结束.Thread-1结束.main结束.总共用时:20860millions可以看到main线程是等所有子线程全部执行完后才开始执行的。
==================================================以下为第二次编辑===============================================上面的方法有一个隐患:如果线程1开始并且结束了,而其他线程还没有开始此时runningThreads的size也为0,主线程会以为所有线程都执行完了。
解决办法是用一个非简单类型的计数器来取代List型的runningThreads,并且在线程创建之前就应该设定好计数器的值。
MyCountDown类Java代码收藏代码public class MyCountDown {private int count;public MyCountDown(int count){this.count = count;}public synchronized void countDown(){count--;}public synchronized boolean hasNext(){return (count > 0);}public int getCount() {return count;}public void setCount(int count) {this.count = count;}}ImportThread类Java代码收藏代码public class ImportThread extends Thread {private MyCountDown c;public ImportThread(MyCountDown c) {this.c = c;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "开始...");//打印开始标记//Do somethingc.countDown();//计时器减1System.out.println(Thread.currentThread().getName() + "结束. 还有" + c.getCount() + " 个线程");//打印结束标记}}主线程中Java代码收藏代码System.out.println(Thread.currentThread().getName() + "开始");//打印开始标记MyCountDown c = new MyCountDown(threadNum);//初始化countDownfor (int ii = 0; ii < threadNum; ii++) {//开threadNum个线程Thread t = new ImportThread(c);t.start();}while(true){//等待所有子线程执行完if(!c.hasNext()) break;}System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记打印结果:main开始Thread-2开始...Thread-1开始...Thread-0开始...Thread-3开始...Thread-5开始...Thread-4开始...Thread-5结束. 还有5 个线程Thread-1结束. 还有4 个线程Thread-4结束. 还有3 个线程Thread-2结束. 还有2 个线程Thread-3结束. 还有1 个线程Thread-0结束. 还有0 个线程main结束.更简单的方法:使用java.util.concurrent.CountDownLatch代替MyCountDown,用await()方法代替while(true){...}ImportThread类Java代码收藏代码public class ImportThread extends Thread {private CountDownLatch threadsSignal;public ImportThread(CountDownLatch threadsSignal) {this.threadsSignal = threadsSignal;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "开始...");//Do somethingsthreadsSignal.countDown();//线程结束时计数器减1System.out.println(Thread.currentThread().getName() + "结束. 还有" + threadsSignal.getCount() + " 个线程");}}主线程中Java代码收藏代码CountDownLatch threadSignal = new CountDownLatch(threadNum);//初始化countDownfor (int ii = 0; ii < threadNum; ii++) {//开threadNum个线程final Iterator<String> itt = it.get(ii);Thread t = new ImportThread(itt,sql,threadSignal);t.start();}threadSignal.await();//等待所有子线程执行完System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记打印结果:main开始Thread-1开始...Thread-0开始...Thread-2开始...Thread-3开始...Thread-4开始...Thread-5开始...Thread-0结束. 还有5 个线程Thread-1结束. 还有4 个线程Thread-4结束. 还有3 个线程Thread-2结束. 还有2 个线程Thread-5结束. 还有1 个线程Thread-3结束. 还有0 个线程main结束.分享到:JavaEye怎么回事?s\cript竟成敏感词?| 未给Editor指定icon引发的异常2010-01-27 19:34。