🍎一.Thread类的属性与方法
🍇1.1什么是线程
一个线程就是一个 “执行流”. 每个线程之间都可以按照顺讯执行自己的代码. 多个线程之间 “同时” 执行
着多份代码.
举个例子如下场景:
一家公司要去银行办理业务,既要进行财务转账,又要进行福利发放,还得进行缴社保。如果只有张三一个会计就会忙不过来,耗费的时间特别长。为了让业务更快的办理好,张三又找来两位同事李四、王五一起来帮助他,三个人分别负责一个事情,分别申请一个号码进行排队,自此就有了三个执行流共同完成任务,但本质上他们都是为了办理一家公司的业务。此时,我们就把这种情况称为多线程,将一个大任务分解成不同小任务,交给不同执行流就分别排队执行。其中李四、王五都是张三叫来的,所以张三一般被称为主线程(Main Thread)。
🍇1.2Thread类的基础常见的构造方法
序号 | 方法 | 解释 |
1 | Thread() | 创建线程对象 |
2 | Thread(Runnable target) | 使用 Runnable 对象创建线程对象 |
3 | Thread(String name) | 创建线程对象,并命名 |
4 | Thread(Runnable target, String name) | 使用 Runnable 对象创建线程对象,并命名 |
5 | 【了解】Thread(ThreadGroup group,Runnable target) | 线程可以被用来分组管理,分好的组即为线程组,这个目前我们了解即可 |
Thread t1 = new Thread(); //我们需要创建一个类来继承Runnable类,在实例化,下文在创建我会给读者朋友演示的 Thread t2 = new Thread(new MyRunnable()); Thread t3 = new Thread("这是我的名字"); Thread t4 = new Thread(new MyRunnable(), "这是我的名字");
🍇1.3Thread的常见属性
属性 | 获取方法 |
ID | getName() |
状态 | getState() |
优先级 | getPriority() |
是否后台线程 | isDaemon() |
是否存活 | isAlive() |
是否被中断 | isInterrupted() |
ID 是线程的唯一标识,不同线程不会重复
名称是各种调试工具用到
状态表示线程当前所处的一个情况,下面我们会进一步说明
优先级高的线程理论上来说更容易被调度到
关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
是否存活,即简单的理解,为 run 方法是否运行结束了
线程的中断问题,下面我们进一步说明
🍇1.4Thread类常用的基础方法
🍎二.Java线程的创建
🍇2.1继承Thread类来创建线程
//MyThread来继承Thread类并且重写了run方法 class MyThread extends Thread{ @Override public void run(){ System.out.println("hello 1"); } } public class dome1 { public static void main(String[] args) { Thread thread = new MyThread(); //记住只有执行start方法是线程才上真正的创建成功 thread.start(); } }
🍇2.2继承Runnable接口创建线程
//MyRunnable来继承Runnable接口,并且在run方法中重写要执行的内容 class MyRunnable implements Runnable{ @Override public void run(){ System.out.println("hellow 3"); } public class dome3 { public static void main(String[] args) { Thread thread3 = new Thread(new MyRunnable()); thread3.start(); } }
🍇2.3使用内部类创建线程
public class demo4 { public static void main(String[] args) { Thread thread4 = new Thread(){ @Override public void run(){ System.out.println("hello 4"); } }; thread4.start(); } }
🍇2.4使用Runnable作为对象来创建线程
public class deom5 { public static void main(String[] args) { Thread thread5 = new Thread(new Runnable() { @Override public void run() { System.out.println("hello 5"); } }); thread5.start(); } }
🍇2.5使用Lambda创建线程
public class deom5 { public static void main(String[] args) { Thread thread5 = new Thread(()-> { System.out.println("hello 5"); }); thread5.start(); } }
🍎三.Java多线程并发基础实现与Thread类常用方法
🍇3.1多线程并发的简单实现
public class demo7 { public static void main(String[] args) { Thread thread7 = new Thread(new Runnable(){ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("Thread线程在执行"); try { Thread.sleep(1000);//休眠一秒,每过一秒打印一次 } catch (InterruptedException e) { e.printStackTrace(); } } } }); thread7.start(); for (int i = 0; i < 10; i++) { System.out.println("main线程在执行"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
从上面的运行结果可以看出一个问题,因为thread线程与main线程都是每打印一句语句线程休眠1秒,两个线程唤醒的先后顺序是随机的,这也是java多线程中的一个“万恶之源”,这个问题给我们带来了很多麻烦,后续的博客我会细说
🍇3.2多线程与单线程效率的区别
public class demo8 { //创建一个不可更改成员实数count public static final long count = 10_0000_0000; //多线程使用方法 public static void thread() throws InterruptedException { //获取开始执行时间戳 long start = System.currentTimeMillis(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { int a = 0; for (int i = 0; i < count; i++) { a++; } } }); thread1.start(); Thread thread2 = new Thread(new Runnable() { @Override public void run() { int b = 0; for (int i = 0; i < count; i++) { b++; } } }); thread2.start(); thread1.join();//需要抛异常 thread2.join(); //获取结束执行时间戳 long end = System.currentTimeMillis(); System.out.println("多线程执行时间:" + (end - start) + "ms"); } //单线程方法 public static void one(){ //获取开始执行时间戳 long start = System.currentTimeMillis(); int a =0; for (int i = 0; i < count; i++) { a++; } int b =0; for (int j = 0; j < count; j++) { b++; } //获取结束执行时间戳 long end = System.currentTimeMillis(); System.out.println("单线程执行时间:" + (end - start) + "ms"); } public static void main(String[] args) throws InterruptedException { //多线程 thread();//因为thread方法执行了join方法所以要在main抛异常 //单线程 one(); } }
我们发现在执行大量计算执行结束后多线程的效率是比单线程执行的效率要快很多