创建方式一:继承Thread类
1.创建一个继承于Thread类的子类
2.重写Thread类中的run():将此线程执行的操作声明在run()中
3.创建Thread类的子类的对象
4.通过此对象调用start():启动当前线程;调用当前线程的run()
public class Exercise1 {
public static void main(String[] args) {
Method1 m1=new Method1();
m1.setName("method1");
m1.start();
}
}
class Method1 extends Thread{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
创建方式二:实现Runnable接口
1.创建一个实现了Runnable接口的类
2.实现类去实现Runnable中的抽象方法:run()
3.创建实现类的对象
4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
5.通过Thread类的对象调用start()
public class Exercise2 {
public static void main(String[] args) {
Method2 m2=new Method2();
Thread t=new Thread(m2);
t.setName("method2");
t.start();
}
}
class Method2 implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
方式一和方式二两种创建方式的对比
1.开发中优先选择:实现Runnable接口的方式
原因:(1)实现的方式没有类的单继承性的局限性
(2)实现的方式更适合来处理多个线程有共享数据的情况
2.相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中
创建方式三:实现Callable接口 ——JDK5.0新增
1.创建一个实现Callable的实现类
2.实现call()方法,将此线程需要执行的操作声明在call()中
3.创建Callable接口实现类的对象
4.将此Callable接口实现类的对象作为参数传递到FutureTask构造器中,创建FutureTask的对象
5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
6.获取Callable中call()方法的返回值。
public class ThreadNew {
public static void main(String[] args) {
//3.创建Callable接口实现类的对象
NumThread numThread=new NumThread();
//4.将此Callable接口实现类的对象作为参数传递到FutureTask构造器
// 中,创建FutureTask的对象
FutureTask futureTask=new FutureTask(numThread);
//5.将FutureTask的对象作为参数传递到Thread类的构造器中
// ,创建Thread对象,并调用start()
new Thread(futureTask).start();
try {
//6.获取Callable中call()方法的返回值。
//get()返回值即为FutureTask构造器参数
// Callable实现类重写的call()的返回值。
Object sum = futureTask.get();
System.out.println("sum="+sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
//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++){
if(i%2==0){
System.out.println(i);
sum+=i;
}
}
return sum;
}
}
方式二和方式三两种创建方式的对比
如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?
(1)call()可以有返回值
(2)call()可以抛出异常,被外边的操作捕获,获取异常的信息
(3)Callable是支持泛型的
创建方式四:使用线程池——JDK5.0新增
1.提供指定线程数量的线程池
2.执行指定的线程的操作。需要土工实现Runnable接口或Callable接口实现类的对象
3.关闭连接池
public class ThreadPool {
public static void main(String[] args) {
//1.提供指定线程数量的线程池
ExecutorService service = Executors.newFixedThreadPool(2);
// //设置线程池的属性
// System.out.println(service.getClass());
// ThreadPoolExecutor service1= (ThreadPoolExecutor) service;
// service1.setCorePoolSize(15);
//2.执行指定的线程的操作。需要土工实现Runnable接口或Callable接口实现类的对象
service.execute(new NumberThread());//适合于使用Runnable
service.execute(new NumberThread1());//适合于使用Runnable
//service.submit();//适合于使用Callable
//3.关闭连接池
service.shutdown();//关闭连接池
}
}
class NumberThread implements Runnable{
@Override
public void run() {
for (int i=0;i<100;i++){
if(i%2==0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
class NumberThread1 implements Runnable{
@Override
public void run() {
for (int i=0;i<100;i++){
if(i%2 !=0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
本文详细介绍了Java中创建线程的四种方式:继承Thread类、实现Runnable接口、实现Callable接口以及使用线程池。重点对比了实现Runnable接口和Callable接口的区别,以及线程池的使用。在开发中,由于避免单继承限制和便于共享数据,通常优先选择实现Runnable接口。Callable接口相比Runnable,提供了返回值和异常处理功能,且支持泛型。

被折叠的 条评论
为什么被折叠?



