进程
正在运行中的程序就是一个进程。 确切的来说,当一个程序进入内存运行,即是一个或多个进程在运行,具有一定独立功能
线程
线程是进程中的一个执行单元,执行路径。是程序使用CPU的最基本单位。 负责当前进程中程序的执行, 程序的执行其实都是在抢CPU的资源,CPU的执行权。 一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。 线程的分类 * 单线程:同一时间只能干一件事情。 * 多线程:同一时间可以干多件事情。Java是属于多线程程序 多线程的优缺点: 多线程并不能提高运行速度,但可以提高运行效率,让 CPU 的使用率更高。 并且,如果多线程有安全问题的处理时,运算速度反而更低。
进程和线程的作用
进程:用来封装线程的,为线程运行提供资源(内存) 线程:用来执行代码的
Java 中的多线程
A:java 支持多线程 B:当 java 程序执行 main 方法的时候,就是在执行一个名字叫做 main 的线程. 可以在 main 方法执行时,开启多个线程 A,B,C 多个线程 main,A,B,C 同时执行,相互抢夺 CPU C:Thread 类是 java.lang 包下的一个常用类,每一个 Thread 类的对象,就代表一个处于某种状态的线程.
主线程和子线程的概念
主线程的概念 * 什么是主线程 * 程序启动时系统自动创建并执行main方法的线程则称为主线程。 * 主线程的执行路径 * 从main方法开始直到main结束。 子线程的概念 * 什么是子线程 * 除了主线程以为的所有线程都称为子线程。 * 子线程的执行路径 * 从run方法开始直到run方法结束。
线程的运行模式
* 分时式模式:每个线程平均分配CPU的使用权。 * 抢占式模式:优先级高的线程会有更高的几率抢到CPU的执行权。我们是不敢保证哪一个线程能够在哪个时刻抢到 Java程序的线程运行模式是属于抢占式模式。
jvm虚拟机的启动是单线程的还是多线程的?
多线程的。 原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。 现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,jvm的启动其实是多线程的。
Thread 类的一些方法:
public final String getName() 获取线程名称 public final void setName(String name) 指定线程名称 public static Thread csurrentThread() 获得当前方法执行所在的线程对象。 static void sleep(long millis) 让当前方法执行所在的线程休眠指定的毫秒数。
继承 Thread 类创建线程
1,指定线程执行目标:定义一个 Thread 类的子类,重写 run 方法,将相关逻辑实现 public void run() 线程要执行的业务逻辑方法,相当于该想成的"main 方法" 2,创建自定义的线程子类对象 3,调用start方法开启线程。 public void start() 使该线程开始执行
//指定线程执行目标:定义一个 Thread 类的子类,重写 run 方法,将相关逻辑实现 public void run() public class MyThread extends Thread { public void run() { int num=0; while(num<100){ try { Random ra=new Random(); // 让线程休眠4s Thread.sleep(ra.nextInt(4000)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("一个子线程"+this.getName()+"在运行:"+num++); } } }
//创建自定义的线程子类对象 MyThread t1=new MyThread(); // 设置线程名称 t1.setName("子线程(1)"); //开启线程动作 t1.start(); MyThread t2=new MyThread(); t2.setName("子线程(2)"); t2.start();
实现 Runnable 接口创建线程
* 创建一个类实现Runnable接口 * 重写Run方法,将线程任务相关代码写在该方法中 * 创建Runnable接口实现类对象 * 根据实现类对象创建Thread类对象,调用start方法
public class MyRunnable implements Runnable { private int number = 1; public void run() { //返回当前线程 Thread thisThread = Thread.currentThread(); int num=1; while(number<10){ try { Random ra=new Random(); Thread.sleep(ra.nextInt(4000)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("一个子线程"+thisThread.getName()+"在运行:"+num++); System.out.println("目标运行次数:"+number++); } }
//创建Runnable接口的实现类对象 MyRunnable mr = new MyRunnable(); // 创建线程对象 Thread thread = new Thread(mr); thread.setName("子线程(3)"); Thread thread2 = new Thread(mr); thread2.setName("子线程(4)"); //开启线程 thread.start(); thread2.start();
实现Runnable接口的好处
屏蔽的Java类单继承的局限性。
可以更好的实现资源共享。
将线程和任务进行了分离,降低了程序的耦合性。
两种实现方式对比
A:第二种方式实现 Runnable 接口避免了单继承的局限性,所以较为常用。 B:实现 Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。 继承 Thread 类,线程对象和线程任务耦合在一起。 一旦创建 Thread 类的子类对象,既是线程对象,有又有线程任务。 实现 runnable接口,将线程任务单独分离出来封装成对象,类型就是 Runnable 接口类型。 Runnable 接口对线程对象和线程任务进行解耦。
使用匿名内部类创建线程
//方式一: //使用匿名内部类创建线程的子类对象 Thread thread = new Thread() { public void run() { System.out.println("我执行了线程1"); } }; thread.start(); //使用匿名内部类创建线程的子类匿名对象 new Thread() { public void run() { System.out.println("我执行了线程2"); } }.start(); //方式二: //使用匿名内部类的方式,创建线程执行目标类对象 //创建线程执行目标类对象 Runnable runnable = new Runnable() { public void run() { System.out.println("我执行线程目标1"); } }; //通过目标创建线程对象 Thread thread2 = new Thread(runnable); //开启线程 thread2.start(); //方式三: //使用匿名内部类的方式,创建线程执行目标类匿名对象 //创建线程执行目标类对象 //通过目标创建线程对象 Thread thread3 = new Thread(new Runnable() { public void run() { System.out.println("我执行线程目标2"); } }); //开启线程 thread3.start(); //方式四: //使用匿名内部类的方式,创建线程执行目标类匿名对象,并且创建的是线程的匿名对象 //创建线程执行目标类对象 //通过目标创建线程对象 new Thread(new Runnable() { public void run() { System.out.println("我执行线程目标3"); } }).start();