精华帖 (6) :: 良好帖 (5) :: 新手帖 (13) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-02-29
说一说java的concurrent包6–java里面的线程基础类Thread
http://www.hetaoblog.com/%E8%AF%B4%E4%B8%80%E8%AF%B4java%E7%9A%84concurrent%E5%8C%856%E2%80%93concurrent%E5%8C%85%E4%B9%8B%E5%89%8D%E7%9A%84synchronized%E5%85%B3%E9%94%AE%E5%AD%97/ 有网友建议我在介绍concurrent包之前先介绍下jdk1.5之前的多线程知识,这是个相当不错的想法, 这篇就先介绍下Thread类; Thread类是java中的线程,几乎所有的多线程都在Thread这个类的基础之后展开; 下面介绍这个类的基本用法,Thread类的最基本函数就是run函数 public void run() 简单的说来,基本的创建一个完成自己功能的线程可以继承Thread类,然后override这个run方法, 如下所示 public class ThreadDemo { @Test public void testThread() { SimpleThread t = new SimpleThread(); t.start(); } } class SimpleThread extends Thread{ @Override public void run() { System.out.println( Thread.currentThread().getName() + " is running "); } } 通常在run方法里面实现自己要做的功能,这里简单的打印了了一句话, 运行结果是 Thread-0 is running 启动一个线程就是new一个自己的Thread对象,然后调用其中的start方法启动这个线程;注意, run()方法运行结束之后这个线程的生命周期就结束了; 上面举的例子是说启动一个线程就去完成一个任务,有的时候我们需要一个线程始终在跑,定期执行一些任务,然后在某个时刻停止这个线程的运行; 那么可以有类似下面的一段代码: public class ThreadDemo { public static void main(String[] args) { PeriodicalRunningThread t = new PeriodicalRunningThread(); t.start(); System.out.println("main thread is going to sleep..."); try { Thread.currentThread().sleep(20 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(new Date() + " now to stop PeriodicalRunningThread"); t.setRunning(false); } } class PeriodicalRunningThread extends Thread{ private volatile boolean running = true; @Override public void run() { while(running) { System.out.println(new Date() + " " + Thread.currentThread().getName() + " is running " + new Date()); try { Thread.currentThread().sleep(5 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(new Date() + " " + Thread.currentThread().getName() + " will end"); } public void setRunning(boolean running) { this.running = running; } } 这段代码的打印结果是: main thread is going to sleep… Wed Feb 29 21:10:39 CST 2012 Thread-0 is running Wed Feb 29 21:10:39 CST 2012 Wed Feb 29 21:10:44 CST 2012 Thread-0 is running Wed Feb 29 21:10:44 CST 2012 Wed Feb 29 21:10:49 CST 2012 Thread-0 is running Wed Feb 29 21:10:49 CST 2012 Wed Feb 29 21:10:54 CST 2012 Thread-0 is running Wed Feb 29 21:10:54 CST 2012 Wed Feb 29 21:10:59 CST 2012 now to stop PeriodicalRunningThread Wed Feb 29 21:10:59 CST 2012 Thread-0 will end 这里通过一个volatile的boolean值来作为标识表示这个线程的停止; 关于这里的volatile关键字的使用,如有兴趣可以先看这个,核桃博客也会在这个系列的后续文章中对这个关键字做说明 http://www.ibm.com/developerworks/cn/java/j-jtp06197.html 这样,在这个running标识为true的时候,该线程一直在跑,但是完成一段任务后会sleep一段时间,然后继续执行; |
|
返回顶楼 | |
发表时间:2012-03-01
要是有实际的案例来,而不是将知识点的话,就好了
|
|
返回顶楼 | |
发表时间:2012-03-01
说一说java的concurrent包7–Thread和Runnable
http://www.hetaoblog.com/%E8%AF%B4%E4%B8%80%E8%AF%B4java%E7%9A%84concurrent%E5%8C%857%E2%80%93thread%E5%92%8Crunnable/ 这篇还是Thread和Runnable的基础 在前面一篇的代码里面已经介绍了Thread类的其他几个常用的方法, 1. sleep函数,作用是让当前线程sleep一段时间,单位以毫秒计算; public static void sleep(long millis) 2. 静态方法Thread.currentThread(), 得到当前线程 public static Thread currentThread() 3. getName方法,得到当前线程名称 public final String getName() 这个名称可以在构造Thread的时候传入, 也可以通过setName()方法设置;这个在多线程调试的时候是比较有用的,设置当前线程名,然后在log4j的输出字符串格式里面加入%t,就可以在日志中打印当前线程名称,方便看到当前的日志是从哪里来的; 现在介绍下多线程里面另外一个重要的接口Runnable, 这个接口表示可以被一个线程执行的任务,事实上Thread类也实现了这个Runnable接口; 这个接口只有一个函数, 实现者只要在里面调用代码就可以了 void run() 同时, Thread类有个构造函数是传入一个Runnable实现的; 常用的一个用法就是通过匿名内部类来创建线程执行简单任务,避免写太多的类,外部需要的变量可以通过加final修饰符后传入, 代码例子如下: public static void testThreadWithRunnable() { final String word = "hello,world"; new Thread(new Runnable() { @Override public void run() { System.out.println(word); } }).start(); } public static void main(String[] args) { //periodicalThreadTest(); testThreadWithRunnable(); } 上面的代码会打印 hello,world |
|
返回顶楼 | |
发表时间:2012-03-01
内容不错,就是排版太难看了,话说你的核桃博客广告也忒多了吧...
|
|
返回顶楼 | |
发表时间:2012-03-01
endual 写道 要是有实际的案例来,而不是将知识点的话,就好了
谢谢大家关注,我会先说基础知识和概念,尽量结合简单的代码例子,其实这些代码也是一些实际代码的简单抽象; 后续尽可能的加上实际案例,不过老实说我的实际经验也比较简单,基本就是例子代码的实际场景应用; 当然对于多线程编程我个人的建议是不需要的时候别用,需要的时候简单用,别把简单的问题复杂化,因为这极有可能带来疑难bug或者调试时间 |
|
返回顶楼 | |
发表时间:2012-03-01
learnworld 写道 内容不错,就是排版太难看了,话说你的核桃博客广告也忒多了吧...
哈,博客模板大约是2年以前搞的,我也一直觉得不好:) 改版正在计划中,你可以看下现在的首页,广告略微少了一点; 话说要做个好看/舒服/合理的界面对我有点难度,只能一步一步慢慢改进~ |
|
返回顶楼 | |
发表时间:2012-03-01
用了一段时间了,发个多线程计算的例子吧。
package test; /** * 并行计算数组的和 * */ import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; public class ConcurrentCalculator { private ExecutorService exec; private int cpuCoreNumber; private List<Future<Long>> tasks = new ArrayList<Future<Long>>(); // 内部类 class SumCalculator implements Callable<Long> { private int[] numbers; private int start; private int end; public SumCalculator(final int[] numbers, int start, int end) { this.numbers = numbers; this.start = start; this.end = end; } public Long call() throws Exception { Long sum = 0l; for (int i = start; i < end; i++) { sum += numbers[i]; } return sum; } } public ConcurrentCalculator() { cpuCoreNumber = Runtime.getRuntime().availableProcessors(); exec = Executors.newFixedThreadPool(cpuCoreNumber); } public Long sum(final int[] numbers) { // 根据CPU核心个数拆分任务,创建FutureTask并提交到Executor for (int i = 0; i < cpuCoreNumber; i++) { int increment = numbers.length / cpuCoreNumber + 1; int start = increment * i; int end = increment * i + increment; if (end > numbers.length) end = numbers.length; SumCalculator subCalc = new SumCalculator(numbers, start, end); FutureTask<Long> task = new FutureTask<Long>(subCalc); tasks.add(task); if (!exec.isShutdown()) { exec.submit(task); } } return getResult(); } /** * 迭代每个只任务,获得部分和,相加返回 * * @return */ public Long getResult() { Long result = 0l; for (Future<Long> task : tasks) { try { // 如果计算未完成则阻塞 Long subSum = task.get(); result += subSum; } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } return result; } public void close() { exec.shutdown(); } public static void main(String args[]) { int[] numbers = new int[] { 1, 2, 3, 4 }; ConcurrentCalculator calc = new ConcurrentCalculator(); Long sum = calc.sum(numbers); System.out.println(sum); calc.close(); } } |
|
返回顶楼 | |
发表时间:2012-03-01
楼主几年工作经验?
|
|
返回顶楼 | |
发表时间:2012-03-01
多线程新手请教一下楼主,最后一个例子里,根据cpu拆分起到啥作用?后面的程序有利用cup个数来操作的吗
|
|
返回顶楼 | |
发表时间:2012-03-01
还得请教一下。。
如果单纯地计算数组的话,为啥不直接采用如下方式。。。 Long sum = 0l; for(int i=0;i<numbers.length;i++){ sum += numbers[i]; } System.out.println(sum); 因为测了一下,你的例子速度比直接循环算的要慢。。 请教请教。。。 |
|
返回顶楼 | |