多线程创建的四种方式
来源:互联网 发布:守望先锋生涯数据出错 编辑:程序博客网 时间:2024/06/05 19:11
多线程的创建之—-继承Thread类
继承Thread类。并重写run()方法,然后启动线程
1、自定义MyThread类,继承Thread类
2、在MyThread类中重写run方法
3、创建MyThread类的对象
4、启动线程对象(start方法是Thread类的方法)
1、举个小例子:
MyThread类:
public class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(this.getName() + ":" + i); } }}
测试类:
public class MyThreadDemo { public static void main(String[] args) { MyThread myThread = new MyThread(); //创建MyThread类的线程对象 MyThread myThread2 = new MyThread(); //创建MyThread类的线程对象 myThread.start(); //启动线程 myThread2.start(); //启动线程 }}
控制台输出:只截取一部分,看个效果即可。因为数据量太大。
Thread-0:0Thread-1:0Thread-0:1Thread-1:1Thread-1:2
2、为什么我调用getName()方法后,它的名字显示的是Thread-的形式呢?
我们来看看源码:
private char name[];//MyThread 类会有一个默认无参构造,这个构造默认会默认调用父类Thread的无参构造public MyThread extends Thread{ public MyThread(){ super(); }}//第一步:public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0);}//第二步private static int threadInitNumber; //默认值是0private static synchronized int nextThreadNum() { return threadInitNumber++;}//第二步private void init(ThreadGroup g, Runnable target, String name, long stackSize) { init(g, target, name, stackSize, null);}//第三步private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) { //大部分代码我没粘贴过来,我只留了主要的代码,可以自己去看源码 this.name = name.toCharArray();}//第四步public final String getName() { return String.valueOf(name);}
这样思路就该清晰了:
(1)、在MyThread类中调用getName()方法,这个方法在MyThread中是没有定义的,因此它调用的是父类的方法。
(2)、加载Thread()类,无参构造中,调用了init(四个参数),然后init(四个参数)又调用了init(五个参数),在init(五个参数)方法中,把this.name = name.toCharArray();把传进来的参数准换成char数组赋值给了全局的char[] name
(3)、在getName()方法中,把全局的char[] name转换为了String字符串,然后显示在界面上
3、但是Thread-这样的名字并不好区分和辨认,也没有实际的意义,因此我们会想到给自己的线程设定指定的名字。
public class MyThreadDemo { public static void main(String[] args) { //创建线程 MyThread myThread = new MyThread(); MyThread myThread2 = new MyThread(); //给线程设置名字 myThread.setName("这是第一个线程"); myThread2.setName("这是第二个线程"); myThread.start(); myThread2.start(); }}
那我们来看看setName()的源码到底是什么样的:我们可以发现setName()把传递过来的name参数准换位字符数组,然后getName()再把字符数组转换成字符串进行输出。
private char name[];public final void setName(String name) { checkAccess(); this.name = name.toCharArray();}public final String getName() { return String.valueOf(name);}
4、上面的是采用无参构造+setName()实现的,现在我们采用带参构造给线程起名字
MyThread类:
public class MyThread extends Thread { public MyThread() { } //继承父亲的带参构造方法 public MyThread(String name) { super(name); } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(this.getName() + ":" + i); } }}
测试类:
public class MyThreadDemo { public static void main(String[] args) { //创建线程,并且给线程起名字 MyThread myThread = new MyThread("这是第一个线程"); MyThread myThread2 = new MyThread("这是第二个线程"); myThread.start(); myThread2.start(); }}
5、获取main方法所在的线程对象的名称。(获取不是Thread类的子类的线程对象的名称)
public static Thread currentThread():返回对当前正在执行的线程对象的引用。
public class MyThreadDemo { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()); //main }}
多线程的创建之—-实现runable接口
1、自定义MyRunable类实现Runnable接口
2、在MyRunable类中重写run()方法
3、创建MyRunable类的对象
4、创建Thread类的对象,并把MyRunable的对象作为构造参数传递进去(因为只有Thread类才有start方法,因此Thread类有一个构造方法是,runnable对象作为参数传递进去创建一个thread对象的方法,这样由thread对象调用start方法)
MyRunnable类:
public class MyRunnable implements Runnable { @Override public void run() { for(int i = 0;i < 100;i++){ //由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接使用。 System.out.println(Thread.currentThread().getName()+":"+i);; } }}
测试类:
public class MyRunnableDemo { public static void main(String[] args) { // 创建MyRunnable类的对象 MyRunnable mr = new MyRunnable(); // 创建Thread类的对象,并把MyRunnable类的对象作为构造参数传递 Thread t1 = new Thread(mr,"小骨"); Thread t2 = new Thread(mr,"玥公子"); t1.start(); t2.start(); }}
多线程的创建之—-使用Callable接口和Future接口(依赖于线程池存在的)(太复杂,不推荐使用)
从java5之后,java提供了Callable接口,Callable接口提供了一个call()方法可以作为线程的执行体,但call()方法比run()方法功能更强大,call()方法可以有返回值,call()方法可以声明抛出异常。
java5提供了Future接口来代表Callable接口里call()方法的返回值,并为Future接口提供了一个FutureTask实现类,该实现类中实现了Future接口,并实现了Runnable接口。可以作为Thread类的target.
但是Callable接口是依赖线程池存在的。
要了解线程池,可以去看这篇文章:http://blog.csdn.net/qq_36748278/article/details/78142968
//Callable接口:带泛型的接口//call()方法的返回值类型就是接口指定的泛型,如果不指定就是Object类型//依赖线程池操作public class MyCallable implements Callable<Integer>{ private int number; public MyCallable(int number) { this.number = number; } @Override public Integer call() throws Exception { int sum = 0; for (int i = 0; i < number; i++) { sum += i; } return sum; }}
public class CallableDemo { public static void main(String[] args) throws InterruptedException, ExecutionException { // 创建线程池对象 ExecutorService pool = Executors.newFixedThreadPool(2); // 可以执行Runnable对象或者Callable对象代表的线程 Future<Integer> future = pool.submit(new MyCallable(100)); Future<Integer> future2 = pool.submit(new MyCallable(200)); Integer i1 = future.get(); Integer i2 = future2.get(); System.out.println(i1 + "," + i2); pool.shutdown(); }}
多线程的创建之—-匿名内部类实现多线程
匿名内部类的格式:(本质是创建该类或者接口的子类对象)
new 类名或接口名(){
重写方法
}
public class ThreadDemo { public static void main(String[] args) { //继承Thread类来实现多线程 new Thread() { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } }.start(); //实现Runnable接口来实现多线程 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("runnable" + ":" + i); } } }){}.start(); //走子类对象thread,不走Runnable接口的 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("runnable" + ":" + i); } } }){ public void run() { for (int i = 0; i < 100; i++) { System.out.println("thread" + ":" + i); } } }.start(); }}
- 多线程创建的四种方式
- Java多线程四种创建方式
- java-多线程-基本概念/四种种创建thread的方式
- 多线程的创建方式
- 多线程的创建方式
- 多线程的创建方式
- Ui 实现多线程的四种方式
- JAVA多线程实现的四种方式
- JAVA多线程实现的四种方式
- Java多线程的四种实现方式
- Android多线程的四种方式
- Android多线程的四种方式
- JAVA多线程实现的四种方式
- Java多线程实现的四种方式
- Java多线程实现的四种方式
- JAVA多线程实现的四种方式
- JAVA多线程实现的四种方式
- JAVA多线程实现的四种方式
- Linux创建用户并加入sudoers文件
- 实现HttpClient重试
- 原生js实现的鼠标滑上去之后按照屏幕高度放大缩略图
- Window 透明窗体的实现总结
- OpenCV-将JPG图像的第二个通道和第三个通道的值设置为最大值
- 多线程创建的四种方式
- oracle 存储过程 ,触发器练习
- 关键字volatite
- hadoop hdfs uri详解 一、hdfs基本命令: hadoop fs -cmd <args> 选项: cmd: 具体的操作,基本上与UNIX的命令行相同 args: 参数 二、hdfs资
- ovs-ofctl 官方文档学习笔记
- 前言
- 四大组件之——server(服务)及Aidl(接口定义语言)
- [BZOJ1345][Baltic2007]序列问题Sequence(单调栈)
- Navicat for MySQL的1577错误解决