两个构造方法 空参和有参
空参Thread():分配一个新的thread对象,不可指定名字
有参 Thread(String name):创建一个新线程,可起名
常用方法:
start():开启线程
run():执行 描述任务
sleep(long millis):设置毫秒值 让正在执行的线程休眠
创建线程步骤
1.先继承thread类 2.重写run 3.创建子类对象(线程对象)4.调用start方法,开启线程让线程执行,让jvm调用run方法
线程对象调run和调start区别
线程调用run不开启线程。调Start 开启线程,让jvm调用run在开启线程中执行
Thread类是个默认类,用来描述,我们定义的这个线程做Thread的子类,是为了利用其Thread本有的功能,子继承父,并拥有它的功能
创建线程目的:
目的有单独路径,让多部分代码同时执行
原理图
看似两个方法同时在运行,其实是CPU快速的切换所以两边都在执行
package com.oracle.demo01; 新建子类 public class MyThread extends Thread{ // 重写run方法 public void run() { for(int i=0;i<20;i++){ System.out.println("myThread-"+i); } super.run(); } }
package com.oracle.demo01; 测试 public class Demo01 { public static void main(String[] args) { // 创建新线程(创建子类对象) MyThread thread=new MyThread(); // 开启线程 调start() thread.start(); for(int i=0;i<20;i++){ System.out.println("main-"+i); } } }
获取线程名称
currentThread():用谁调用就会返回调用当前方法线程的对象
getName():以前获取方法名是用报错的方法获取名称,现在可以直接用getName来代表
在新线程里获得名称,直接用getName就可以,因为里面没有静态
在main里想获得主线程,先获得主线程的对象,在获得主线程名称
package com.oracle.demo01; //定义一个类继承Thread public class MyThread extends Thread{ // 重写run方法 public void run() { // getName()获取当前线程名称 System.out.println("线程名称为"+getName()); for(int i=0;i<20;i++){ System.out.println("myThread-"+i); } super.run(); } }
package com.oracle.demo01;
//用.currentThread()获取名称 public class Demo01 { public static void main(String[] args) { // 获取执行当前代码线程的线程对象 Thread th=Thread.currentThread(); // 获取该线程的名称 System.out.println(th.getName()); // 创建新线程(创建子类对象) MyThread thread=new MyThread(); // 开启线程 调start() thread.start(); for(int i=0;i<20;i++){ System.out.println("main-"+i); } } }
接口中的方法 run():
Thread类构造方法
步骤:
1.定义类实现Runnable接口
2. 覆盖接口的run方法
3.创建Thread类对象
4 .强Runnable接口子类对象作为参数传递给Thread类的构造函数
5.调用Thread类的start()开启线程
package com.oracle.demo01; //定义一个类 实现Runnable //让它实现Runnable 让MyRunnable作为新线程任务 public class MyRunnable implements Runnable{ public void run() { for(int i=0;i<20;i++){ System.out.println("Thread-0"+i); } } }
package com.oracle.demo01; //测试Runnable类接口 public class Demo02 { public static void main(String[] args) { // 创建线程任务对象 :MyRunnable:描述任务 MyRunnable mr=new MyRunnable(); // 创建Thread类对象:开启线程 Thread th=new Thread(mr); // 开启线程 th.start(); for(int i=0;i<20;i++){ System.out.println("main-"+i); } } }
Runnable是Thread的接口,“推荐用接口的方式”生成线程,因为接口可以实现多继承 避免单一继承局限性,如果用Thread类,只能继承和创建Thread,如果用Runnable可以实现后可再继承,比Thread多了个备用功能 覆盖Runnable接口的run方法,将线程任务定义到run方法中。将线程的任务从线程的子类中分离出来,进行了单独的封装,按照面向对象思想将任务封装成对象
匿名内部类最后得到的是子类或实现对象
package com.oracle.demo01; //两个匿名内部类方式 public class Neibulei { public static void main(String[] args) { /*new 父类或接口名(){ 需要重写方法 }*/ // 1.创建线程方式 继承Thread类 new Thread(){ // 重写run(): 写出run然后alt+/ public void run() { System.out.println(getName()+"这是新线程任务"); } // 匿名内部类方式:创建和开启线程一步到位 }.start(); // 2.实现Runnable接口 Runnable run=new Runnable(){ public void run() { // 获取当前执行线程对象 String name=Thread.currentThread().getName(); System.out.println(name+"这是匿名内部类第二个方式"); } // 最后得到的是线程任务对象 }; new Thread(run).start(); } }
pm
概念:一个容纳多个线程的容器,可以反复使用,省去创先线程的操作,不用反复创建,消耗资源
线程状态图
Runnable接口:都是通过线程池工厂创建,再调用线程池中的方法获取线程,再通过线程去执行任务方法
public class MyRun implements Runnable{ public void run() { // 获取执行当前线程对象的名字 String name=Thread.currentThread().getName(); for(int i=0;i<20;i++){ System.out.println(name+i); // 不能throws try { Thread.sleep(1000);//休眠毫秒值 } catch (InterruptedException e) { e.printStackTrace(); } } } }
线程池原理图:
public class Demo01 { public static void main(String[] args) { // 创建线程任务对象 MyRun mr= new MyRun(); // 创建新线程对象 Thread th =new Thread(mr); // 开启线程 th.start(); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Demo02 { public static void main(String[] args) { // 用线程池的方式完成线程任务 // 1.从线程池工厂中获取一个装有两条线程的线程池对象 ExecutorService es=Executors.newFixedThreadPool(2); // 2.创建线程任务 MyRun mr=new MyRun(); // 3.让线程池自主选一条线程执行线程任务(第二个会等第一个的有空了就执行) es.submit(mr); es.submit(mr); es.submit(mr); /*//关闭线程池(一般不关闭) es.shutdown();*/ } }
import java.util.concurrent.Callable; public class MyCallable implements Callable<String>{ public String call() throws Exception { return "abc"; }
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Demo01 { public static void main(String[] args) throws InterruptedException, ExecutionException { // 1.从线程池工厂中获取线程池对象 ExecutorService es=Executors.newFixedThreadPool(2); // 2.创建线程任务对象 MyCallable mc=new MyCallable(); // 3.让线程池自主选择一条线程执行线程任务 Future<String> f=es.submit(mc); // 4.获取线程任务的返回值 System.out.println(f.get()); } }
Future接口:记录线程任务执行完毕后产生的结果 线程池创建与使用
get() 获取Future对象中封装的数据结果
import java.util.concurrent.Callable; public class MyCall implements Callable<Integer>{ private int num; private int num1; public MyCall(){} public MyCall(int num,int num1){ this.num=num; this.num1=num1; } public Integer call() throws Exception { // 计算求和 int sum=0; for(int i=num;i<=num1;i++){ sum+=i; } return sum; } }
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Demo01 { //用线程池计算50到100的和------44.....200的和 public static void main(String[] args) throws InterruptedException, ExecutionException { // 1.从线程池工厂获取线程池对象 ExecutorService es=Executors.newFixedThreadPool(2); // 2.创建线程任务对象 MyCall mc1=new MyCall(50,100); MyCall mc2=new MyCall(44,200); // 3.让线程池自主选择线程执行任务 Future<Integer> f1=es.submit(mc1); Future<Integer> f2=es.submit(mc2); // 4.获取线程任务返回值 int sum1=f1.get(); int sum2=f2.get(); System.out.println(sum1); System.out.println(sum2); } }
原文:https://www.cnblogs.com/zs0322/p/11066960.html