Java多线程基础知识整理
一,程序,进程,线程
* 1.程序:指令集,静态概念;
* 2.进程:操作系统 调度程序 动态概念
* 3.线程:在进程内多条执行路径
* main方法和gc和异常
* 程序是一个静态的概念;进程:是一个动态的概念;
* 进程是程序的一次动态执行过程,占用特定的地址空间;
* 每个进程都是独立的
* 由3部分组成cpu data code;
* 缺点:内存的浪费,cpu的负担
*线程:是进程中一个“单一的连续控制流程”
*线程又被称为轻量级进程;一个进程可拥有多个并行的线程;一个进程中的线程共享相同的内存单元/内存地址空间(因此会
*造成并发问题),
*可以访问相同的变量和对象,而且他们从同一堆中分配对象;
进程:
* 作为资源分配的单位;
* 每个进程都有独立的代码和数据空间,进程间的切换会有较大的开销;
* 在操作系统中能同时运行多个多个任务;
* 系统在运行的时候为每个进程分配不同的内存区域;
* 没有线程的进程可以看成是多线程,如果一个进程内拥有多个线程,则执行过程不是一条线的,
* 而是多条线程共同完成的;
线程:
* 线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器,
* 线程切换的开销较小;
* 在同一应用程序中有多个顺序流同时执行;
* 除了cpu之外,不会为线程分配内存,线程所使用的资源是它所属进程的资源,线程组只能共享资源,
* 线程是进程的一部分,所以线程有的时候被称为是轻权进程或者轻量级进程;
java实现多线程(一)
* 在Java中负责线程的功能是Java.lang.Thread这个类; 可以通过创建Thread的实例来创建新的线程;
* 每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run称为线程体;
* 通过调用thread类的start方法来启动一个线程;(java是单继承多实现,此方法不被建议)
public class Thread02 { /** * 模拟龟兔赛跑 创建多线程 继承thread +重写run 使用线程:创建子类对象+对象的start方法 */ public static void main(String[] args) { Rabbit r = new Rabbit(); r.start(); Tortoise t=new Tortoise(); t.start(); } } public class Rabbit extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("兔子跑了" + i + "步"); } } } public class Tortoise extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("乌龟" + i + "步"); } } }
二)使用Runnable接口
* 类实现runnable接口加上实现run方法,真实角色类, 推荐使用第二种: (1)避免单继承 (2)便于共享资源 (不能抛出异常,没有返回值);
public class Thread03 implements Runnable { @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("一边敲代码"); } } } public class Thread03App { public static void main(String[] args) { Thread03 t = new Thread03(); Thread proxy = new Thread(t); proxy.start(); for (int i = 0; i < 1000; i++) { System.out.println("一边聊qq"); } } }
* java实现多线程(三)
* 使用Callable接口(Java.util.Concurrent)创建线程,优点:可以获取返回值
package Tread; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Thread04 { public static void main(String[] args) throws InterruptedException, ExecutionException { //创建线程 ExecutorService ser = Executors.newFixedThreadPool(2); Race tor = new Race("tor", 1000); Race rabbit = new Race("rabbit", 500); //获取值 Future<Integer> res=ser.submit(tor); Future<Integer> res2=ser.submit(rabbit); Thread.sleep(2000); // 停止循环 tor.setFlag(false); rabbit.setFlag(false); Integer num= res.get(); Integer num2 = res2.get(); System.out.println("乌龟跑了"+num); System.out.println("兔子跑了"+num2); //停止服务 ser.shutdownNow(); } } class Race implements Callable<Integer> { private String name; private int time; private int step = 0; boolean flag = true; public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public Race(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getTime() { return time; } public void setTime(int time) { this.time = time; } public int getStep() { return step; } public void setStep(int step) { this.step = step; } public Race(String name, int time) { super(); this.name = name; this.time = time; } public Race() { super(); } @Override public Integer call() throws Exception { while (flag) { Thread.sleep(time); step++; } return step; } }
* Callable接口和Future接口
* Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他现场执行的 任务
* Callable接口和Runnable接口有几点不同:
* (1)Callable接口规定的方法是Call,而Runnable规定的方法是Run;
* (2)call方法可以抛出异常,Runnable方法不行;
* (3)Callable的任务执行后可返回值,运行Callable任务可拿到一个Future返回值,而Runnable的任务是没有返回值的
* Future表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果,通过Future对象可了解
* 任务执行情况,可取消任务的执行,还可获取执行的结果
* 缺点:繁琐
* 思路:
1)创建Callable实现类+重写call;
* 2)借助执行调度服务ExecuteService,获取Future对象 ExecuteService
ser=Executors.newFixedThreadPool(2); Future result=ser.submit(实现类对象);
* 3)获取值:result.get;
4)停 止服务:ser.shutdownnow();