线程的创建有
1.继承thread类
继承Thread类创建线程的步骤为:
(1)创建一个类继承Thread类,重写run()方法,将所要完成的任务代码写进run()方法中;
(2)创建Thread类的子类的对象;
(3)调用该对象的start()方法,该start()方法表示先开启线程,然后调用run()方法;
public class Thread1 {
public static void main(String[] args) {
Thread.currentThread().setName("主线程");
System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
//创建一个新线程
ThreadDemo1 thread1 = new ThreadDemo1();
//为线程设置名称
thread1.setName("线程一");
//开启线程
thread1.start();
}
}
class ThreadDemo1 extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
}
}
2.runnable接口
(1)创建一个类并实现Runnable接口
(2)重写run()方法,将所要完成的任务代码写进run()方法中
(3)创建实现Runnable接口的类的对象,将该对象当做Thread类的构造方法中的参数传进去
(4)使用Thread类的构造方法创建一个对象,并调用start()方法即可运行该线程
public class Thread2 {
public static void main(String[] args) {
Thread.currentThread().setName("主线程");
System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
//创建一个新线程
Thread thread2 = new Thread(new ThreadDemo2());
//为线程设置名称
thread2.setName("线程二");
//开启线程
thread2.start();
}
}
class ThreadDemo2 implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
}
}
3.使用callable
callable是一个函数式接口,因此可以用作lambda表达式或方法引用的赋值对象。
callable与runnable两者创建线程得对比
创建新类MyThread实现runnable接口
class MyThread implements Runnable{
@Override
public void run() {
}
}
新类MyThread2实现callable接口
class MyThread2 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
return 200;
}
}
面试题:callable接口与runnable接口的区别?
答 (1)是否有返回值
(2)是否抛异常
(3)落地方法不一样,一个是run,一个是call
那callable可以直接替代runnable吗?答案是不可以,因为Thread中没有callable得构造方法.看javaAPI文档
4.线程池
(1)使用Executors类中的newFixedThreadPool(int num)方法创建一个线程数量为num的线程池
(2)调用线程池中的execute()方法执行由实现Runnable接口创建的线程;调用submit()方法执行由实现Callable接口创建的线程
(3)调用线程池中的shutdown()方法关闭线程池
public class Thread4 {
public static void main(String[] args) throws Exception {
Thread.currentThread().setName("主线程");
System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
//通过线程池工厂创建线程数量为2的线程池
ExecutorService service = Executors.newFixedThreadPool(2);
//执行线程,execute()适用于实现Runnable接口创建的线程
service.execute(new ThreadDemo4());
service.execute(new ThreadDemo6());
service.execute(new ThreadDemo7());
//submit()适用于实现Callable接口创建的线程
Future<String> task = service.submit(new ThreadDemo5());
//获取call()方法的返回值
String result = task.get();
System.out.println(result);
//关闭线程池
service.shutdown();
}
}
//实现Runnable接口
class ThreadDemo4 implements Runnable{
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
}
}
//实现Callable接口
class ThreadDemo5 implements Callable<String>{
@Override
public String call() throws Exception {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
return Thread.currentThread().getName()+":"+"返回的结果";
}
}
//实现Runnable接口
class ThreadDemo6 implements Runnable{
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
}
}
//实现Runnable接口
class ThreadDemo7 implements Runnable{
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
}
}
最后在说说FutureTask,首先FutureTask是什么,举一个例子
例子:
(1)老师上着课,口渴了,去买水不合适,讲课线程继续,我可以单起个线程找班长帮忙买水,
水买回来了放桌上,我需要的时候再去get。
(2)4个同学,A算1+20,B算21+30,C算31*到40,D算41+50,是不是C的计算量有点大啊,
FutureTask单起个线程给C计算,我先汇总ABD,最后等C计算完了再汇总C,拿到最终结果
(3)高考:会做的先做,不会的放在后面做
在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给Future对象在后台完成,
当主线程将来需要时,就可以通过Future对象获得后台作业的计算结果或者执行状态。
一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成,
就不能再重新开始或取消计算。get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,
然后会返回结果或者抛出异常。
只计算一次
get方法放到最后
最后通过代码来实现FutureTask.
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
class MyThread implements Runnable{
@Override
public void run() {
}
}
class MyThread2 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"come in callable");
return 200;
}
}
public class CallableDemo {
public static void main(String[] args) throws Exception {
//FutureTask<Integer> futureTask = new FutureTask(new MyThread2());
FutureTask<Integer> futureTask = new FutureTask(()->{
System.out.println(Thread.currentThread().getName()+" come in callable");
TimeUnit.SECONDS.sleep(4);
return 1024;
});
FutureTask<Integer> futureTask2 = new FutureTask(()->{
System.out.println(Thread.currentThread().getName()+" come in callable");
TimeUnit.SECONDS.sleep(4);
return 2048;
});
new Thread(futureTask,"zhang3").start();
new Thread(futureTask2,"li4").start();
//System.out.println(futureTask.get());
//System.out.println(futureTask2.get());
//1、一般放在程序后面,直接获取结果
//2、只会计算结果一次
while(!futureTask.isDone()){
System.out.println("***wait");
}
System.out.println(futureTask.get());
System.out.println(Thread.currentThread().getName()+" come over");
}
}
注:对于futureTask我也还有未弄懂得,学习过后再补上