线程是什么:
进程是程序的一次动态执行的过程,线程是进程中执行运算最小单位,一个进程在其执行过程中可以产生多个线程,而线程必须在某个进程内执行。
如果在一个进程中同时运行了多个线程(必须包含一个主线程),用来完成不同的工作,则称之为“多线程”多个线程交替占用CPU资源,而非真正的并行执行
主线程:
main()方法即为主线程入口
产生其他子线程的线程
必须最后完成执行,因为它执行各种关闭动作
一、创建线程的三种方法:
1.Thread类创建线程
继承Thread类,重写run()方法,线程要执行的操作放在run()方法中,通过调用start()方法来启动线程。start()方法只属于Thread类
注意:创建线程对象时不会执行线程,必须调用线程对象的start方法才能使线程开始
线程每次执行时长由分配的CPU时间片长度决定
主线程:
public class TestThread {
public static void main(String[] args) {
//查看主线程
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
//启动子线程
MyThread myThread = new MyThread();
myThread.start();
}
}
子线程:
public class MyThread extends Thread{
@Override
public void run(){
for (int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"==="+i);
}
}
}
查看线程名字:
查看线程名:Thread.currentThread().getName()
这里的currentThread()是静态方法
public static void main(String[] args) {
//查看主线程
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
//或者
System.out.println( Thread.currentThread().getName());
}
直接调用run()和start()区别:
使用run( )方法 | 同步执行,只有主线程一条执行路径 |
使用star( )方法 | 异步执行,多条执行路径,主线程和子线程并行交替执行 |
- 直接调用run()就是同步执行,main方法会等run方法执行完以后才会执行下面的操作;
- 调用star()方法可以实现异步执行,由线程调度器决定先执行main方法还是run方法,不是由程序代码中的
start()
调用的顺序直接决定的。
同步和异步:
也就是说一个程序需要运行完了有结果了才能进行下一个线程,这样这个程序就会堵塞其他的程序,这就是同步,异步就是这个程序在运行的时候我仍然可以不管他运行别的程序
多线程可以将同步程序变为异步的,从而增加系统资源的利用率
2.Runnable接口创建线程:
因为Thread是单根继承,继承Thread之后不能够继承其他的类了。使用Runnable接口可以解决这个问题。
Runnable接口中声明了一个run()方法,即public void run()。
例子:使用Runnable接口创建线程
1.实现Runnable接口,并且实现Runnable接口的run()方法
2.创建Thread类对象,使用Runnable接口实现类的对象作为构造方法的参数 Thread td = new Thread(new Test02());
3.调用start方法
子线程:
public class MyRunnalbe implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "===" + i);
}
}
}
主线程:
注意:这个start方法是Thread类独有的
所以要创建一个thread对象,把myRunnalbe装进去
public class TestRunnable {
public static void main(String[] args) {
MyRunnalbe myRunnalbe = new MyRunnalbe();
Thread thread = new Thread(myRunnalbe);
thread.start();
}
}
3.Callable接口创建线程:
首先介绍一下这个接口:
- 它需要重写call方法,而不是run了,
- 并且call()方法有返回值String,用futureTask.get()来接收返回值
- 它是一个泛型,默认返回为Object,可以在泛型中设置想要返回的类型
主程序:
public class TestMyCallable {
public static void main(String[] args) {
MyCallable myCallable = new MyCallable();
FutureTask<String> futureTask = new FutureTask<>(myCallable);
Thread thread = new Thread(futureTask);
thread.start();
//接收返回值
try {
System.out.println(futureTask.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
子线程:
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "===" + i);
}
return "蛋蛋最牛掰";
}
}