简介
本人对线程也是一知半解(用的较少吧!),不成体系,然而这是面试的常问,且有可能深问的一个点,因而决定写线程这一系列的博客,理清自己关于线程的知识。
内容
**创建线程主要是3种方式:
1.继承Thread类(真正意义上的线程类),实现了Runnable接口;
2.实现Runnable接口;(特点:突破继承的局限性,接口可以多实现,类只能单继承);
3.实现Callable<?>接口。
还有一种:
3.使用Executor框架创建线程池。Executor框架是juc里提供的线程池的实现。(下一节线程池的时候具体说)
代码如下(理解也在代码里):
public class ThreadPoolStudy {
public static void main(String[] args) {
//注意:这些线程并不一定是按顺序启动的
//创建并启动线程1
new Thread01().start();
//创建并启动线程2
new Thread(new Thread02()).start();
//创建并启动线程3、
FutureTask<String> futureTask = new FutureTask<String>(new Thread03());
new Thread(futureTask).start();
try {
String str = futureTask.get();
System.out.println(str);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
//Thread类实现了Runnabel接口
class Thread01 extends Thread{
public void run(){
//重写run方法,需要执行的代码
System.out.println("----线程1----");
}
}
//特点:可以突破继承的局限性(接口可以多实现)
class Thread02 implements Runnable{
//实现Runnable接口的类需要再次用Thread类包装后才能调用start方法。(三个Thread对象包装一个类对象,就实现了资源共享)。
// 即new Thread(new Thread02()).start();//创建并启动线程
@Override
public void run() {
//重写run()方法,需要执行的业务
System.out.println("----线程2----");
}
}
/**
* 三、通过Callable和Future创建线程(特点:有返回值且可以抛出异常)
* (1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
* (2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
* (3)使用FutureTask对象作为Thread对象的target创建并启动新线程。
* (4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值或者抛出的异常
*/
class Thread03 implements Callable<String>{
@Override
public String call() throws Exception {
return "----线程3----";
}
}
运行结果(特意找的):
Thread类中主要的方法有:
- 1.start():启动线程并执行相应的run()方法
- 2.run():子线程要执行的代码放入run()方法中
- 3.currentThread():静态的,调取当前的线程
- 4.getName():获取此线程的名字
- 5.setName():设置此线程的名字
- 6.yield():调用此方法的线程释放当前CPU的执行权(很可能自己再次抢到资源)
- 7.join():在A线程中调用B线程的join()方法,表示:当执行到此方法,A线程停止执行,直至B线程执行完毕,
- A线程再接着join()之后的代码执行
- 8.isAlive():判断当前线程是否还存活
- 9.sleep(long l):显式的让当前线程睡眠l毫秒 (只能捕获异常,因为父类run方法没有抛异常)
- 10.线程通信(方法在Object类中):wait() notify() notifyAll()
- 设置线程的优先级(非绝对,只是相对几率大些)
- getPriority():返回线程优先值
- setPriority(int newPriority):改变线程的优先级
start()方法和run()方法的区别
在java多线程中:
- 使用start()方法来启动线程(执行run方法),真正实现了多线程运行。
当start()方法调用时,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。
通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容, - run()方法只是类的一个普通方法,在java多线程中我们一般把需要处理的业务逻辑放在run()中。run方法执行完毕,线程随即终结。