Java多线程备忘

刚好学习Java使用多线程,标准使用是这样的:首先定义一个任务,再使用一个线程去执行这个任务。那么如果不用线程去执行任务或者用线程执行一个没有定义的任务会是什么情况呢?试一试看看


为了方便查看关系,定义一个显示字符的任务类,再定义另一个主线程类,用这个类的main函数去跑。


1. 定义任务 + 不用Thread跑

任务代码:

public class showInfo implements Runnable {

	private String text;
	private int times;
	
	public showInfo(String t, int times) {
		this.text = t;
		this.times = times;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (times-- > 0) {
			System.out.print(text);
		}
	}
}
主线程类:

public class MainThread {
	
	public static void main(String[] args) {
		
		showInfo s1 = new showInfo("hello.", 2);
		showInfo s2 = new showInfo("world.", 3);
		
		s1.run();
		s2.run();
	}
}
结果:

hello.hello.world.world.world.

可以看到,没有用Thread跑,其实定义了Runnable接口也没用,直接去跑还是在主线程里面的,顺序执行。


2. 定义任务 + 用Thread跑

任务不变,新的主线程类:

public class MainThread {
	
	public static void main(String[] args) {
		
		showInfo s1 = new showInfo("hello.", 2);
		showInfo s2 = new showInfo("world.", 3);
		
		Thread t1 = new Thread(s1);
		Thread t2 = new Thread(s2);
		
		t1.start();
		t2.start();
		System.out.println("waiting for show:");
	}
}

结果:

hello.waiting for show:
hello.world.world.world.

整体都错开,CPU时间分片处理效果就出来了。


3. 不实现Runnable接口 + 用Thread跑

如果不实现Runnable接口,Eclipse里面会在Thread创建的时候报错,So。。。


使用线程,就是如此简单,当然,书上提到一个

Thread.yield()

貌似是为了防止线程占用资源,让其暂停一段时间,试着在刚才这段代码中加入了yield(),输出结果变化了:
hello.waiting for show:
world.hello.world.world.

第二排第一个变成了world但是这跟使用yield关系应该不是那么直接,多执行几次,结果还是会变化回去,看来线程分片有些随机性。


4. 线程执行顺序

为了查看线程优先级,修改了任务类,在每个任务开始和结束处都设置了打印信息:
public class showInfo implements Runnable {

	private String text;
	private String name;
	private int times;
	
	public showInfo(String t, int times, String name) {
		this.text = t;
		this.times = times;
		this.name = name;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(name + ": Thread running.");
		while (times-- > 0) {
			System.out.println(text);
			Thread.yield();
		}
		System.out.println(name + ": Thread closing.");
	}
}

在主线程类中一样跑,跑了很多次结果很随机,其中一次如下:
waiting for show:
Thread2: Thread running.
Thread1: Thread running.
hello.
world.
hello.
world.
Thread1: Thread closing.
world.
Thread2: Thread closing.

多加入更多线程,更随机,什么排列都有,当然了,某个线程的打开一定在其关闭之前。


5. Executor
可以管理Thread对象,实际使用能够中,可以用它来创建和管理所有的任务
ExecutorService exec = Executors.newCachedThreadpool();
用来动态加入线程。

ExecutorService exec = Executors.newFixedThreadpool(n);
固定只能加入5个线程,节约资源。多余线程会排队。


exec.shutdown();
用于防止新的线程加入。

6. 从任务中产生返回值
那么就不能使用Runnable了,应该转换为Callable接口,方法call(),必须使用方法Executor.submit()来调用
创建一个待返回值的任务,计算斐波那契数列的和,这个应该能计算很久:
import java.util.concurrent.Callable;

public class FibnacciSum implements Callable<String> {

	private int n;
	final private int UPPER = 100000000;
	
	FibnacciSum(int n){
		this.n = n;
	}
	public String call() {
		// TODO Auto-generated method stub
		int a = 0;
		int b = 1;
		int t = 0;
		for (int i = 0; i < UPPER; i++) {
			t = b;
			b = a + b;
			a = t;
		}
		return n + ":Fib result:" + a;
	}
}

在主线程类中用Executor创建10个任务,并且不断查询结果:
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public class MainThread2 {
	
	public static void main(String[] args) {
		
		ExecutorService exec = Executors.newCachedThreadPool();
		ArrayList<Future<String>> results =
				new ArrayList<Future<String>>();
		
		for (int i= 0; i < 10; i++) 
			results.add(exec.submit(new FibnacciSum(i)));
		
		for (Future<String> fs : results)
			try{
				while (!fs.isDone()) {
					System.out.println("one not done");
				}
				System.out.println(fs.get());
			} catch(InterruptedException e) {
				System.out.println(e);
				return;
			} catch (ExecutionException e) {
				System.out.println(e);
			} finally {
				exec.shutdown();
			}
			
		System.out.println("waiting for show:");
	}
}

这里就查了其中一个结果的值,从显示中可以看出,实现了Callable接口的任务返回一个Future<String>,通过这个对象可以查询对象是否已经准备好,准备好后即可调用。
可以这样: 不断循环查询,哪个好了先显示哪个,最后的结果一定是乱序的。

7. 优先级
任务类中定义 private int priority , 构建任务是写入优先级即可,比如: Thread.MIN_PRIORITY和Thread.MAX_PRIORITY,以及Thread.NORMAL_PRIORITY,由于优先级与系统映射不是很好,所以推荐使用这几个就可以了。

8. 后台线程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值