⼀个线程就是⼀个"执⾏流".每个线程之间都可以按照顺序执⾏⾃⼰的代码.多个线程之间"同时"执⾏
着多份代码.
还是回到我们之前的银⾏的例⼦中。之前我们主要描述的是个⼈业务,即⼀个⼈完全处理⾃⼰的业务。我们进⼀步设想如下场景:
⼀家公司要去银⾏办理业务,既要进⾏财务转账,⼜要进⾏福利发放,还得进⾏缴社保。
如果只有张三⼀个会计就会忙不过来,耗费的时间特别⻓。为了让业务更快的办理好,张三⼜找来两位同事李四、王五⼀起来帮助他,三个⼈分别负责⼀个事情(可以理解为一个进程中包含着多个线程),分别申请⼀个号码进⾏排队,⾃此就有了三个执⾏流共同完成任务,但本质上他们都是为了办理⼀家公司的业务。
此时,我们就把这种情况称为多线程,将⼀个⼤任务分解成不同⼩任务,交给不同执⾏流就分别排队执⾏。其中李四、王五都是张三叫来的,所以张三⼀般被称为主线程(MainThread)。
首先,“并发编程"是"刚需”.
严格意义上来说,一个PCB是描述一个线程的,而进程是若干个PCB合起来描述的.
我们拿一个"合租"的例子来说明上述问题
比如我们合租一间房子,客厅,卫生间,厨房等空间都是公共区域,相当于上述PCB中的内存指针和文件描述符表还有tgid,每个线程之间共享着内存空间和系统文件.每个卧室之间是每个人独有的空间,每个人的房间都不一样,就像上述的pid,线程调度属性.
[举例]
下面有请我们的助教,蔡徐坤老师.
全民制作人们大家好,我是练习时长两年半的个人练习生cxk,喜欢Java,数据结构,数据库,music
注:下面在主方法中创建的线程属于主线程,在程序执行之后会自动启动线程.建议看完后面的1.3的一部分内容之后再来看这里.run()方法,start()方法,构造,sleep()方法都在后面.
public class MyTread extends Thread{
@Override
public void run() {
while (true){
System.out.println("hello tread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {//注意调用sleep方法需要抛出异常
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
Thread thread = new MyTread();
thread.start();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class MyTread1 implements Runnable{
@Override
public void run() {
while (true){
System.out.println("hello tread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
Thread thread = new Thread(new MyTread());
thread.start();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class MyTread2 {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
while (true){
System.out.println("hello tread");
try {
Thread.sleep(1000);//Tread类中的一个static方法
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
};
thread.start();
while (true) {
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class MyTread3 {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println("hello tread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
thread.start();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class MyTread4 {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
while (true){
System.out.println("hello tread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread.start();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
Thread类是JVM⽤来管理线程的⼀个类,换句话说,每个线程都有⼀个唯⼀的Thread对象与之关
联。⽤我们上⾯的例⼦来看,每个执⾏流,也需要有⼀个对象来描述,类似下图所⽰,⽽Thread类的对象就是⽤来描述⼀个线程执⾏流的,JVM会将这些Thread对象组织起来,⽤于线程调度,线程管理.
方法 | 说明 |
---|---|
Tread() | 创建线程对象 |
Tread(Runnable target) | 使用Runnable对象来创建线程 |
Tread(String name) | 创建线程对象并命名 |
Tread(Runnable target,String name) | 使用Runnable对象来创建线程并命名 |
Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");
属性 | 获取方法 |
---|---|
id | getId() |
名称 | getName() |
优先级 | getPriority() |
状态 | getState() |
是否是后台线程 | isDaemon() |
是否存活 | isAlive() |
是否被中断 | isInterrupted() |
拓展:把一个线程设置为后台线程的方法是线程引用.setDaemon(true).
我们下面举一个代码的例子:
public class Demo0 {
public static void main(String[] args) {
Thread thread = new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("tread");
});
thread.setDaemon(true);//把tread线程设置为后台线程
thread.start();
System.out.println("main is terminate");
}
}
运行结果:
这里我们可以看到,只打印了最后main线程的一句话,由于在tread设置为了后台线程,而且在线程中sleep了1s,tread还没来得及反应,前台线程main线程就已经结束了,整个进程就结束了,后台的tread也不得不结束.
我们下面通过一个实际生活中的例子-----吃酒席来说明:
[未完待续…]