提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
本文用自己最通俗的语言解释整理多线程的知识点,请指教
一、什么是多线程?
线程就像是人边看电视,边吃饭,可以同时做多件事,或者说是做多件事之间的时间间隙很短,几乎忽略。放在程序里面,就是完成多件线程。首先要知道不是所有程序语言都支持线程,有些语言只能运行完成一件任务后再进行下一项目的开发,Java提供了线程的并发(多个线程访问同一对象)执行。得区分开和进程的差别,进程是计算机系统的多任务操作系统的单位,是正在执行的程序,也可以多段进程先后执行,而一个进程就具有多个可以并发执行的线程。
二、实现多线程的两种常用方式
1.继承Thread类
代码如下(示例):
package com.java;
public class Solution3 {
public static void main(String[] args) {
System.out.println("main线程执行了");
new MyThread().start();
}
}
class MyThread extends Thread{
@Override
public void run() {
System.out.println("MyThread线程执行了");
}
}
重写run()方法,通过start()方法启动线程
2.实现Runnable接口
代码如下(示例):
package com.java;
public class Solution3 {
public static void main(String[] args) {
System.out.println("main线程执行了");
TestThread1 testThread1 = new TestThread1();
new Thread(testThread1).start();
}
}
class TestThread1 implements Runnable{
@Override
public void run() {
System.out.println("1");
}
}
实质上也是Thread类实现了Runnable,前者中的run方法正是对后者run方法的具体实现,同时,因为Java不支持多继承,为满足需求,常使用实现Runnable接口来使类具有使用线程的的功能。
三、线程的生命周期
线程具有生命周期,其中包含7种状态:
1.出生状态:线程被创建时处于的状态,在调用start()方法前都属于这一状态;
2.就绪状态:调用start后就进这一状态,然后会在就绪与运行状态下转换,同时能进入其他状态;
3.运行状态:得到系统分配的资源后就进入这一状态;
4.等待状态:调用wait方法后,此时不占用系统资源,用notify或notifyAll方法唤醒;
5.休眠状态:调用sleep方法后,占用系统资源;
6.阻塞状态:在运行状态下发出输入/输出请求后会进入阻塞状态;
7.死亡状态:run方法执行完毕后进入死亡状态。
调用Thread.State方法可查看所处状态:
四、操作线程的常用方法
1.线程的休眠
Thread.sleep(1000); //这代表休眠2秒,参数单位是毫秒
它的执行可能会抛出InterruptedException,所以要将它放在try-catch块中
常用来放大线程运行的错误。
小扩展:10秒倒计时
package com.java.practice;
public class Demo001 {
public static void main(String[] args) throws InterruptedException {
tenDown();
}
public static void tenDown() throws InterruptedException {
int nums = 10;
while(true){
Thread.sleep(1000);
System.out.println(nums--);
if(nums == 0){
break;
}
}
}
}
2.线程的加入
Thread.join() 当使用某个线程加入到另一个线程中后,另一个线程会等待该线程执行完毕后再继续执行。就像在打游戏的时候,女朋友打电话进来,必须先接完电话再打游戏!
3.线程的中断
不建议使用JDK中的stop方法,会导致阻塞。
建议利用布尔型标记自定义stop方法,像这样:
private boolean flag = true; @Override public void run() { int i = 0; while(flag){ System.out.println("run thread 跑了"+i++); } } public void stop() { this.flag = false; }
4.线程的礼让
Thread.yield()提醒具有同样优先级的线程可以将资源让出去,但是不一定让得出去,就像100米短跑,我让你先跑,但是你还是不一定能跑得过我,最后谁先冲线(执行完毕)不一定。
五、线程的优先级
字面意思也好理解,这里是把线程的优先级分为1-10级,下面是Thread类中的成员变量:
-
-
static int
MAX_PRIORITY
线程可以拥有的最大优先级。(10)
static int
MIN_PRIORITY
线程可以拥有的最低优先级。(1)
static int
NORM_PRIORITY
分配给线程的默认优先级。(5)也可以自定义
-
-
-
void
setPriority(int newPriority)
更改此线程的优先级。
-
六、线程的同步
为啥要同步?因为线程不安全,就像两个人买电影票,但只剩下1张了,两个人同时去买,最后应该是一人能买到,一人不能买到,线程如果不同步,余票会不会变成-1张。
Java提供了同步机制,可以有效防止资源冲突,使用synchronized关键字
首先是同步块,synchronized(Object){}
package com.java.practice;
public class UnsafeBank {
public static void main(String[] args) {
Account account = new Account(100,"结婚基金");
Drawing you = new Drawing(account,50,"you");
Drawing girl = new Drawing(account,100,"girl");
you.start();
girl.start();
}
}
//账户
class Account{
int money;
String name;
public Account(int money,String name){
this.money = money;
this.name = name;
}
}
class Drawing extends Thread{
Account account;
int drawingMoney;
int nowMoney;
@Override
public void run() {
//锁的是增删改的对象,也就是银行账户;同步块
synchronized (account) {
//判断钱够不够
if (drawingMoney > account.money) {
System.out.println(this.getName() + "钱不够,取不了");
return;
}
account.money = account.money - drawingMoney;
nowMoney = nowMoney + drawingMoney; //更新
System.out.println(account.name + "余额为:" + account.money);
System.out.println(this.getName() + "手里的钱:" + nowMoney);
}
}
public Drawing(Account account, int drawingMoney,String name){
super(name);
this.account = account;
this.drawingMoney =drawingMoney;
}
}
还有同步方法,即在方法前加关键字:
synchronized void f(){}
持续更新中......