学习Java多线程这一篇就够了 |
您所在的位置:网站首页 › 多线程的通信 › 学习Java多线程这一篇就够了 |
目录 进程与线程 进程基本概念及理解 线程基本概念及理解 进程线程对比 创建进程 继承Thread类创建多线程 实现Runnable接口创建多线程 实现Callable接口创建多线程 Thread类与Runnable接口实现多线程对比 线程状态 线程调度 线程的优先级 线程休眠 线程插队 线程让步 线程中断 守护线程 线程同步 同步代码块 同步代码块 同步方法 死锁问题 Lock锁 进程与线程多线程是提升程序性能重要方式,也是java中一项重要的技术。多线程是指一个应用程序中有多条并发执行的线索,每条线索都是一个线程,线程之间可以可以交替执行,彼此可以通信。 进程基本概念及理解程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。 进程则是一个动态的概念,进程则是执行程序的一次执行过程,是系统进行资源分配和调度的基本单位。 程序就是保存在磁盘上,编译好的二进制文件,不占用系统资源进程存在于内存中,占用系统资源一个单核的CPU同一时刻只能处理一个进程在单核CPU背景下,平时我们在一台计算机上,可以同时打游戏,听音乐,语音通话可以同时进行,感觉是有多个进程在运行,但实际上是计算机系统采用了多到程序设计技术,就是在内存管控下,多个进程之间相互穿插执行。 采用多到程序设计的系统会把CPU周期划分为多个长度相同的时间片,在每个时间片内只能处理一个进程,也就是说内存里面的多个进程轮流交替使用CPU。而我们产生错觉的原因是,CPU的时间片非常小,我们难以感受到其中差异。因此在宏观上,可以认为是计算机可以并发执行多个进程。 线程基本概念及理解每个运行的程序就是以一个进程,一个进程里面可以有多个执行单元同时执行,这些执行单元就是线程,每个进程至少有一个线程。线程是CPU调度和执行的的单位。 多线程和单线程的区别: 多线程看起是同时执行的,他们和进程是一样的,由CPU轮流执行,只是CPU执行速度很快,几乎感觉不到。 真正的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错觉 进程线程对比 进程是系统进行资源分配和调度的基本单位,线程是CPU调度和执行的的单位。一个进程里面至少包含一个多线程,可以包含多个。关于多线程理解: 线程就是独立的执行路径;在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;main() 称之为主线程,为系统的入口,用于执行整个程序;在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能认为的干预的。对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;线程会带来额外的开销,如cpu调度时间,并发控制开销每个线程在自己的工作内存交互,内存控制不当会造成数据不一致 创建进程三种创建进程方式: 通过继承Thread类,重写类中run方法,即可实现多线程。 start() 启动新线程,之后Java虚拟机自动调用run方法。 package Example1; // 继承Thread类创建多线程 public class Test1 { public static void main(String[] args) { Mythread mythread = new Mythread(); mythread.start(); while(true) { System.out.println("main()方法在运行"); } } } class Mythread extends Thread { public void run() { while(true) { System.out.println("MyThread类的run方法在运行"); } } }运行结果: Mythread.start()启动新的线程,和之前main()线程里的代码同时执行。 实现Runnable接口创建多线程Thread类提供了一个构造方法,Thread(Runnable target) ,参数是一个接口,它只有一个run方法。 通过这个构造方法创造Thread对象时,需要传递一个Runnable实现接口对象。通过Thread的对象调用start()方法,来执行run()。 这样一来,调用新线程任务就交给Thread执行,原本的类只需要实现Runnable接口即可。可以避免Java单继承的问题。 package Example2; public class Test2 { public static void main(String[] args) { Mythread mythread = new Mythread(); Thread thread = new Thread(mythread); thread.start(); while(true) { System.out.println("main()方法在运行"); } } } // Mythread实现Runnable()接口,并且重写run()方法 class Mythread implements Runnable { public void run() { while(true) { System.out.println("MyThread类的run方法在运行"); } } }运行结果: 前两种创建进程方法存在缺点,无法从run()方法获取返回值。 实现Callable接口可以满足创建多线程和获取返回值的要求。 package Example3; import java.util.concurrent.*; // 实现Callable创建多线程 public class Test3 { public static void main(String[] args) throws InterruptedException,ExecutionException{ // 创建实现Callable接口的实例对象 Mythread mythread = new Mythread(); // 使用FutureTask封装Mythread类 FutureTask ft = new FutureTask(mythread); // 使用Thread(Runnable target,String name)创建线程对象 Thread thread = new Thread(ft,"thread"); // 启动新线程 thread.start(); // currentThread().getName() 当前线程名字 get() 返回管理值 System.out.println(Thread.currentThread().getName()+"的返回结果"+ft.get()); int a=0; while(a++0) { // 调用Thread类种的currentThread().get()获取当前执行线程的名字 Thread th = Thread.currentThread(); //返回一个对象 String name = th.getName(); System.out.println(name+"正在发售第" + tickets-- + "张票"); } } } package Example5; public class Test5 { public static void main(String[] args) { TicketWindow tk = new TicketWindow(); new Thread(tk,"窗口1").start(); new Thread(tk,"窗口2").start(); new Thread(tk,"窗口3").start(); new Thread(tk,"窗口4").start(); } } class TicketWindow implements Runnable { private int tickets=100; public void run () { while(tickets>0) { Thread th =Thread.currentThread(); String name = th.getName(); System.out.println(name + "正在发售第" + tickets-- + "张票"); } } }综合考虑,建议在创建多线陈的时候使用实现Runnable方式创建多线程。 线程状态线程的基本状态:新建,运行,阻塞,等待,中止 线程调度线程调度有两种模型:分时调度模型和抢占式调度模型 分时调度模型:所有线程轮流获得CPU的使用权,就是平均主义抢占式调度模型:根据线程优先级获得CPU使用权,优先级相同则线程随机获得CPU使用权Java虚拟机默认采用抢占式调度模型 线程的优先级优先级高的的线程获得CPU使用权的机会就越大,优先级低的线程获得CPU使用机会越小。 线程的优先级用1-10,数字越大,优先级越高。Thread类中提供了三个静态常量表示线程的优先级。 static int MAX_PRIORITY:表示线程最高优先级,表示10; static int MIN_PRIORITY :表示线程最低级,表示1; static int NORM_PRIORITY:表示线程默认优先级,表示5; package Example6; public class Test6 { public static void main(String[] args) { Thread mp = new Thread(new MaxPriority(),"优先级较高线程"); Thread np = new Thread(new MinPriority(),"优先级较低线程"); mp.setPriority(Thread.MAX_PRIORITY); np.setPriority(Thread.MIN_PRIORITY); mp.start(); np.start(); } } class MaxPriority implements Runnable { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+"正在输出"+i); } } } class MinPriority implements Runnable { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+"正在输出"+i); } } }其实,即使设置了线程的优先级,一样无法确保这个线程一定先执行,因为它有很大的随机性。它并无法控制执行哪个线程,因为线程的执行,是抢占资源后才能执行的操作,而抢点资源时,最多是给于线程优先级较高的线程一点机会而已,能不能抓住可是不一定的。。 线程休眠是指让当前线程暂停执行,从运行状态进入阻塞状态,将CPU资源让给其它线程的调度方式 package Example7; public class Test7 { public static void main(String[] args) throws Exception { new Thread(new SleepThread()).start(); for(int i=1;i |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |