关于Thread和Runnable的一些笔记

下面是一个简单的多线程方法,每个线程可单独执行自己的run方法。

package hello.test;


//关于Thread和Runnable的一些
public class test {
// 有两种创建线程的方法,一种是将类声明为线程的子类。这个子类应该重写类线程的run方法。然后可以分配和启动子类的实例。
class PrimeThread extends Thread {
//可以传一些需要用到的参数进来
long minPrime;

PrimeThread(long minPrime) {
this.minPrime = minPrime;
}

public void run() {
//具体是想用这个线程干什么

}
}

// 创建一个线程并启动它运行
public void test(){
PrimeThread p = new PrimeThread(143);
p.start();
}

// 创建线程的另一种方法是声明实现可运行接口的类。然后,该类实现了run方法。然后可以分配类的实例,在创建线程时作为参数传递,然后启动。

static class PrimeRun implements Runnable {
long minPrime;

PrimeRun(long minPrime) {
this.minPrime = minPrime;
}

public void run() {
for(int i = 0;i<minPrime;i++){
System.out.println(i);
}
}
}

// 创建一个线程并启动它运行
public static void test1(){
PrimeRun p1 = new PrimeRun(10);
new Thread(p1).start();
}

// 每个线程都有一个用于标识的名称。多个线程可以具有相同的名称。如果在创建线程时未指定名称,则会为其生成新名称。除非另有说明,否则将空参数传递给此类中的构造函数或方法将导致引发NullPointerException。
//可以循环写一个多线程的方法
public static void main(String[] args) {
try {
for( int i = 0;i<4;i++){
test1();
}
} catch (Exception e) {
System.out.println(e);
}
}
}

两种方法有自己的优缺点:

源码中的区别
继承Thread类方式:由于子类重写了Thread类的run(),当调用start()时,直接找子类的run()方法(Java虚拟机自动完成)
实现Runnable方式:构造函数中传入了Runnable的引用,传给了Thread类中的成员变量,start()调用了run()方法时的内部判断成员变量Runnable的引用是否为空,若不为空,编译时看的是Runnable的run(),运行时执行的是具体实现类中的run()
优缺点:
继承Thread类方式
好处:可以直接使用Thread类中的方法,代码简单
弊端:同样也是面向对象中的继承的缺点:如果该具体类已经有了其他的父类,那么就不能多重继承Thread类,就不能使用这种方法。此时面向接口编程的优势脱颖而出。
实现Runnable接口方式
好处:即继承的弊端:即使自己定义的线程类有了其他父类也可以实现该Runnable接口。Java中的接口是多实现的,继承是单继承,比较有局限性。
弊端:不能直接使用Thread类中的方法,需要先把Runnable具体实现类对象传递给Thread类并获取到线程对象后,才能得到Thread类的方法,代码相对复杂

还有一种是Callable实现多线程 这种如果方法需要返回值的话调用,提交给ExecutorService返回值是异步执行的,并且可以抛出异常

public static void main(String[] args) throws InterruptedException, ExecutionException {

//创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2) ;
//此处需要实例化一个本类的对象 因为 在这里,MyCallable是test的内部类,类似于普通的实例变量,如类的静态方法不可以直接调用类的实例变量。在这里,内部类不是静态的内部类,所以,直接赋值(即实例化内部类),所以程序报错。
test test = new test();
//提交任务
Future<Integer> f1 = pool.submit(test.new MyCallable()) ;
Future<Integer> f2 = pool.submit(test.new MyCallable()) ;
Integer i = f1.get();
Integer i1 = f2.get();
System.out.println(i1);
//关闭线程池
pool.shutdown();
}

class MyCallable implements Callable<Integer> {
public MyCallable() {
}

@Override
public Integer call() throws Exception {

int i = 0;
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);

i++;
}
return i;
}
}



 

猜你喜欢

转载自www.cnblogs.com/duidui-li/p/11069900.html