进程就是正在运行的程序,它会占用对应的内存区域,由CPU进行执行与计算。
进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。
线程是操作系统OS能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.
一个进程可以开启多个线程,其中有一个主线程来调用本进程中的其他线程。
我们看到的进程的切换,切换的也是不同进程的主线程
多线程可以让同一个进程同时并发处理多个任务,相当于扩展了进程的功能。
一个操作系统中可以有多个进程,一个进程中可以包含一个线程(单线程程序),也可以包含多个线程(多线程程序);每个线程在共享同一个进程中的内存的同时,又有自己独立的内存空间.
一、继承Thread类创建线程类
(1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
(2)创建Thread子类的实例,即创建了线程对象。
(3)调用线程对象的start()方法来启动该线程。
以下代码中Thread.currentThread()方法返回当前正在执行的线程对象;
GetName()方法返回调用该方法的线程的名字;
public class FirstThreadTest extends Thread { int i = 0; //重写run方法,run方法的方法体就是现场执行体 public void run() { for (; i < 100; i++) { System.out.println(getName() + " " + i); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " : " + i); if (i == 50) { new FirstThreadTest().start(); new FirstThreadTest().start(); } } } }
二、通过Runnable接口创建线程类
(1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
(2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
(3)调用线程对象的start()方法来启动该线程。
public class RunnableThreadTest implements Runnable{ private int i; public void run() { for(i = 0;i <100;i++) { System.out.println(Thread.currentThread().getName()+" "+i); } } public static void main(String[] args) { for(int i = 0;i < 100;i++) { System.out.println(Thread.currentThread().getName()+" "+i); if(i==20) { RunnableThreadTest rtt = new RunnableThreadTest(); new Thread(rtt,"新线程1").start(); new Thread(rtt,"新线程2").start(); } } } }
继承Thread和实现Runnable接口的区别
在我们刚接触的时候可能会迷糊继承Thread类和实现Runnable接口实现多线程,其实在接触后我们会发现这完全是两个不同的实现多线程,一个是多个线程分别完成自己的任务,一个是多个线程共同完成一个任务。
三、覆写Callable接口实现多线程(JDK1.5)
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class MyThread implements Callable<String> { private int count = 20; @Override public String call() throws Exception { for (int i = count; i > 0; i--) { // Thread.yield(); System.out.println(Thread.currentThread().getName()+"当前票数:" + i); } return "sale out"; } public static void main(String[] args) throws InterruptedException, ExecutionException { Callable<String> callable =new MyThread(); FutureTask <String>futureTask=new FutureTask<>(callable); Thread mThread=new Thread(futureTask); Thread mThread2=new Thread(futureTask); Thread mThread3=new Thread(futureTask); // mThread.setName("hhh"); mThread.start(); mThread2.start(); mThread3.start(); System.out.println(futureTask.get()); } }
四.通过线程池启动多线程
(1)使用Executors类中的newFixedThreadPool(int num)方法创建一个线程数量为num的线程池。
(2)调用线程池中的execute()方法执行由实现Runnable接口创建的线程;调用submit()方法执行由实现Callable接口创建的线程。
(3)调用线程池中的shutdown()方法关闭线程池。
public class Thread4 { public static void main(String[] args) throws Exception { Thread.currentThread().setName("主线程"); System.out.println(Thread.currentThread().getName()+":"+"输出的结果"); //通过线程池工厂创建线程数量为2的线程池 ExecutorService service = Executors.newFixedThreadPool(2); //执行线程,execute()适用于实现Runnable接口创建的线程 service.execute(new ThreadDemo4()); service.execute(new ThreadDemo6()); service.execute(new ThreadDemo7()); //submit()适用于实现Callable接口创建的线程 Future<String> task = service.submit(new ThreadDemo5()); //获取call()方法的返回值 String result = task.get(); System.out.println(result); //关闭线程池 service.shutdown(); } } //实现Runnable接口 class ThreadDemo4 implements Runnable{ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+"输出的结果"); } } //实现Callable接口 class ThreadDemo5 implements Callable<String>{ @Override public String call() throws Exception { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+"输出的结果"); return Thread.currentThread().getName()+":"+"返回的结果"; } } //实现Runnable接口 class ThreadDemo6 implements Runnable{ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+"输出的结果"); } } //实现Runnable接口 class ThreadDemo7 implements Runnable{ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+"输出的结果"); } }
Java线程共有5中状态,分别为:新建(new)、就绪(runnable)、运行(running)、堵塞(blocked)、死亡(dead)。
1、新建状态:当创建一个线程时,此线程进入新建状态,但此时还未启动。
2、就绪状态:创建好线程后调用线程的start()方法,该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权。等待期间线程处于就绪状态
3、运行状态:当线程获得cpu的使用权后,线程进入运行状态,开始执行run()方法。
4、阻塞状态:线程在运行过程中可能由于各种原因放弃了cpu 使用权,暂时停止运行,即进入阻塞状态。阻塞的情况分为:等待阻塞、同步阻塞、其他阻塞等三种情况。
5、死亡状态:线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。