一、线程概述
进程:是计算机中的程序关于某数据集合的一次运行活动,是操作系统进行资源分配和调度的基本单位
线程:是操作系统能够进行运算调度的最小单位,一个线程就是进程中一个单一顺序的控制流,进程是线程的容器,一个进程至少有一个线程,一个进程可以有多个线程
OS中是以进程为单位分配资源,如虚拟存储控件、文件描述符。每个线程都有自己的线程栈
JVM启动时会自动创建一个主线程,该主线程负责执行main方法。主线程就是运行main方法的线程。
串行、并行、并发

二、线程的创建与启动
2.1 继承Thread类的形式创建线程
在Java中,创建一个线程就是创建一个Thread类(子类)的对象(实例)
Thread类有两个常用的构造方法:Thread()与Thread(Runnable)对应的创建线程的两种方式
这两种方法没有本质的区别
public class Thread01 extends Thread{
public static void main(String[] args) {
System.out.println("JVM创建main线程执行main方法");
Thread01 thread01 = new Thread01();
//调用start()方法来启动线程,实质就是请求JVM运行相应的线程,这个线程具体什么时候运行由OS的线程调度器(Scheduler)决定
//start()方法调用结束并不意味着子线程开始运行
//新开启的进行会执行run方法
//如果开启了多个线程,start()调用的顺序并不一定就是线程的启动顺序!
//多线程运行结果和代码调用顺序无关
thread01.start();
System.out.println("main线程其他的代码...");
}
//run()方法的代码就是子线程要执行的任务
//run()方法执行完线程就执行完了
@Override
public void run() {
System.out.println("这是子线程打印的东西");
}
}

2.2 多线程运行结果是随机的
public class Thread02 extends Thread{
public static void main(String[] args) {
Thread02 thread02 = new Thread02();
thread02.start();
for(int i = 0; i < 10; i++){
System.out.println("main thread: " + i);
try {
// Math.random() -> [0,1]的小数
int time = (int) (Math.random()*1000);
Thread.sleep(time);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
@Override
public void run() {
for(int i = 0; i < 10; i++){
System.out.println("sub thread: " + i);
try {
// Math.random() -> [0,1]的小数
int time = (int) (Math.random()*1000);
Thread.sleep(time);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}

2.3 实现Runnable接口创建线程
把线程的具体实现交给Thread实例,本类只需实现Runnable接口,写出具体实现
/**
* 当线程已经有父类了,就不能用继承Thread类创建线程
* 可以使用实现Runnable接口的形式
* 1)定义类实现Runnable接口
*/
public class MyRunnable implements Runnable{
// 2)重写Runnable接口中的抽象方法run()
// run()方法就是子线程要执行的代码
@Override
public void run() {
for(int i = 0; i < 100; i++){
System.out.println("sub thread -> " + i);
}
}
public static void main(String[] args) {
// 3)创建Runnable接口的实现类对象
MyRunnable runnable = new MyRunnable();
// 4)创建线程对象
Thread t = new Thread(runnable);
// 5) 启动线程
t.start();
for(int i = 0; i < 100; i++)
System.out.println("main thread -> " + i);
}
}
接口引用指向实现类的对象
接口引用调用实现类对象实现该接口的方法run()方法
本质是内存指向,对象空间
耦合度低



为什么要用接口引用指向实现类的对象?
这种写法其实Java多态的表现形式(一个接口类型的引用变量来引用实现接口的类的实例,当这个引用调用方法时,它会根据实际引用的类的实例来判断具体调用哪个方法)
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
为什么一般都使用 接口引用指向子类对象 ,而不用 实现类本身 引用呢?
问题就在于接口可以有多个实现类,如果现在你使用这个实现类接收,也许哪一天你需要换成其它的实现类呢?
这时你只要将new的实现类对象换成你想要的就行了, 其它地方的代码根本不需要改动。
三、线程的常用方法
currentThread()方法
Thread.currentThread()方法可以获得当前线程
Java中的任何一段代码都是执行在某个线程当中的。执行当前代码的线程就是当前线程
同一段代码可能被不同的线程执行,因此当前线程是相对的,Thread.currentThread()方法的返回值是在实际运行时候的线程对象
public class SubThread1 extends Thread{
public SubThread1(){
System.out.println("SubThread1构造方法 -> " + Thread.currentThread().getName());
}
//由Thread类中的方法调用执行
@Override
public void run() {
// currentThread() native关键字修饰,调用C语言接口
System.out.println("run方法 -> " + Thread.currentThread().getName());
}
public static void main(String[] args) {
System.out.println("main -> " + Thread.currentThread().getName());
SubThread1 subThread1 = new SubThread1();
subThread1.start();
}
}

一个复杂案例
893

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



