创建三种线程的方式对比
使用实现Runnable、Callable接口的方式创建多线程。
优势
Java的设计是单继承的设计,如果使用继承Thread的方式实现多线程,则不能继承其他的类,而如果使用实现Runnable接口或Callable接口的方式实现多线程,还可以继承其他类。
采用接口能够更好的实现数据共享。线程的启动需要Thread类的start方法,如果采用继承的方式每次新建一个线程时,每个新建线程的数据都会单独的存在线程内存中,这样每个线程会单独的操作自己线程的数据,不能更好的实现线程之间的数据共享。
劣势
编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。
使用继承Thread的方式实现多线程测试案例
public class ThreadTest extends Thread{
public int count = 10;
@Override
public void run() {
count--;
System.out.println(this.getName()+"的count:"+count);
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new ThreadTest();//thread1有自己的数据——count
Thread thread2 = new ThreadTest();//thread2有自己的数据——count
thread1.start();
Thread.sleep(100);
thread2.start();
}
}
运行结果
Thread-0的count:9
Thread-1的count:9
使用实现Runnable、Callable接口的方式创建多线程测试案例
public class RunnableTest implements Runnable{
public int count = 10;
@Override
public void run() {
count--;
System.out.println(Thread.currentThread().getName()+"的count:"+count);
}
public static void main(String[] args) throws InterruptedException {
RunnableTest runnableTest = new RunnableTest();
//threa1和threa2共享同一个数据——count
Thread thread1 = new Thread(runnableTest);
Thread thread2 = new Thread(runnableTest);
thread1.start();
Thread.sleep(100);
thread2.start();
}
}
运行结果
Thread-0的count:9
Thread-1的count:8
使用继承Thread类的方式创建多线程
-
优势:
编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。 -
劣势:
线程类已经继承了Thread类,所以不能再继承其他的类。
Runnable和Callable的区别
与Runnable相比,Callable功能更强大些
- Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。
- Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
- call方法可以抛出异常,run方法不可以。
- Callable是支持泛型的
- 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
Runnable接口源码
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Callable接口源码
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result //可以有返回值
* @throws Exception if unable to compute a result //可以抛出异常
*/
V call() throws Exception;
}
Callable接口使用案例
/*
创建线程的方式三:实现Callable接口。-----JDK1.5新增
*/
//1.创建一个实现Callable的实现类
class NumThread implements Callable{
//2.实现call方法,将此线程需要执行的操作声明在call()中
@Override
public Object call() throws Exception{
int sum=0;
for (int i=1;i<=100;i++){
sum+=i;
}
return sum;
}
}
public class ThreadNew {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//3.创建Callable接口实现类的对象
NumThread numThread=new NumThread();
//4.将此Callable接口实现类的对象作为传递到FutureTask构造中,创建FutureTask的对象
FutureTask futureTask=new FutureTask(numThread);
//5.将FutureTask的对象组排位哦参数传递到thread类的构造器中,创建Thread对象,并调用start()
new Thread(futureTask).start();
//6.获取Callable中call方法的返回值
//get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值
Object sum = futureTask.get();
System.out.println("总和为:"+sum);
}
}
Threa类基本属性和方法(最基本的)
基本属性
/**
* 线程的优先级
* 线程分为10个优先级,分别用整数1——10表示,其中1为最低优先级,10为最高优先级,5为默认优先级,
* 在操作系统中,线程可以划分优先级,线程优先级越高,获得 CPU 时间片的概率就越大,但线程优先级的高低与线程的执行顺序并没有必然联系,优先 * 级低的线程也有可能比优先级高的线程先执行。
*/
// 线程可以具有的最高优先级
static int MAX_PRIORITY
// 线程可以具有的最低优先级
static int MIN_PRIORITY
// 分配给线程的默认优先级(默认为5)
static int NORM_PRIORITY
基本方法
//返回对当前正在执行的线程对象的引用
static Thread currentThread()
//返回该线程的名称
String getName()
//返回线程的优先级
int getPriority()
//如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
void run()
//设置线程名称
void setName(String name)
//设置线程的优先级。
void setPriority(int newPriority)
//使该线程开始执行,Java 虚拟机调用该线程的 run 方法。
void start()