好久没用多线程了,复习一下~~
1.几种调用多线程的方式(部分源码摘自 《Thinking in Java》)
①:实现Runnable接口,见下面例子:
class LiftOff implements Runnable{
protected int countDown=10;
private static int taskCount=0;
private final int id=taskCount++;
public LiftOff(){}
public LiftOff(int countDown){
this.countDown=countDown;
}
public String status(){
return "#"+id+"("+(countDown>0?countDown:"LiftOff")+")";
}
@Override
public void run() {
// TODO Auto-generated method stub
while(countDown-- >0){
System.out.println(status());
Thread.yield();
}
}
}
public class method1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
LiftOff launch = new LiftOff(10);
launch.run();
}
}
注意,这里 启动线程采用的run()函数
2.Thread类:或者继承Thread类
public class methdo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread thread = new Thread(new LiftOff());
thread.start();
}
}
这里的Thread的构造函数需要传入一个实现了Runnable接口的对象,他启动 线程采用start()函数;
3.Executor
public class method3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService exe = Executors.newCachedThreadPool();
for(int i=0;i<5;i++){
exe.execute(new LiftOff());
}
exe.shutdown();
}
}
exe.execute()里面传入一个实现了runnable()接口的类,并且执行~ 它启动线程的方式为execute();
对于Executor的创建,主要有以下三种:
newcachedThreadPool:可扩充线程数量的线程池
newFixedThreadPool:创建固定数量线程的线程池
newSingleThreadExecutor:单线程
4.实现Callable接口;
Callable接口是一种具有类型参数的泛型,它的类型参数表示是从方法call()中返回的【注意不是run()】,并且使用ExecutorService.submit()方法调用它
class TaskWithResult implements Callable<String>{
private int id;
public TaskWithResult(int id){
this.id=id;
}
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
return "result of TaskWithResult "+id;
}
}
public class method4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> result =new ArrayList<Future<String>>();
for(int i=0;i<10;i++){
result.add(exec.submit(new TaskWithResult(i)));
}
for(Future<String> fs:result){
try {
System.out.println(fs.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
exec.shutdown();
}
}
}
}
submit方法会产生Future对象。
如题调用多线程就以上四种方式~
2.守护线程和普通线程
守护线程是在程序运行的时候在后台提供一种通用服务的线程。它可以缺省~
它与普通线程的区别有以下几点:
①:创建:要设置守护线程,必须要在启动之前设置为setDaemon()方法,而普通线程不需要这一步。
②:守护线程创建的任何线程都是守护线程;而普通线程都可以创建。
③:守护线程不会执行finally里面的语句;普通线程会执行。
④:程序要在普通线程运行完才会终止;但是却不会等守护线程运行完:即如果main函数执行完,无论守护线程是否执行完都会终止。
3.多线程里面的几个关键字
①join:如果线程A在线程B中上调用A.join,A线程挂起,等线程B执行完~
class Sleeper extends Thread{
private int duration;
public Sleeper(String name,int sleepTime){
super(name);
duration=sleepTime;
start();
}
public void run() {
try {
sleep(duration);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println(getName()+" was interrupted."+" isInterrupted " +isInterrupted());
}
System.out.println("awakend");
}
}
class Joiner extends Thread{
private Sleeper sleeper;
public Joiner(String name,Sleeper sleeper){
super(name);
this.sleeper=sleeper;
start();
}
public void run(){
try {
sleeper.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("interrupted..");
}
System.out.println(getName()+" join complete..");
}
}
public class join {
public static void main(String[] args){
Sleeper s = new Sleeper("sleeper",1500);
Joiner j = new Joiner("joiner", s);
}
}
输出结果肯定是:先执行完Sleeper中的,在执行joiner中的~,结果如下:
awakend
joiner join complete..
如果没有join的话,即如果如下:
joiner join complete..
awakend
②:interrupt:将该线程设定一个标志,表示该线程已经被打断。
还是上面的例子:只改最后一个类
public class join {
public static void main(String[] args){
Sleeper s = new Sleeper("sleeper",1500);
Joiner j = new Joiner("joiner", s);
s.interrupt();
}
}
我们可以看到输出:
sleeper was interrupted. isInterrupted false
awakend
joiner join complete..
23.