- 浏览: 139600 次
文章分类
最新评论
-
wangyudong:
很有帮助的代码实例,测试Spring Boot REST AP ...
1、springboot入门案例helloworld与集成hibernate -
wangyudong:
学习了,的确是一个非常好的Spring boot实例,很快就写 ...
1、springboot入门案例helloworld与集成hibernate
想了解线程,必须先了解进程,因为线程是依赖进程存在的。
什么是进程?
进程就是正在运行的程序;是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。
多进程有什么意义?
单进程的计算机只能做一件事情,而我们现在的计算机可以做多件事情。
举例:一边玩游戏,一边听音乐等
现在的计算机都支持多进程的,可以在一个时间段内执行多个任务。并且,可以提高CPU使用率。
什么是线程?
在同一个进程内又可以执行多个任务,而每一个任务可以看成是一个线程。
线程:是程序的执行单元,执行路径。是程序使用CPU的最基本单位。
单线程:如果程序只有一条执行路径。
多线程:如果程序有多条执行路径。
多线程有什么意义呢?
多线程的存在,不是提高程序的执行速度。其实是为了提高应用程序的使用率。
程序的执行其实都是在抢CPU的资源,CPU的执行权。
多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的机率抢到CPU的执行权。
我们不敢保证哪一个线程能够在哪个时刻抢到,所以线程执行有随机性。
并行和并发的区别:
并行:是逻辑上同时发生,指在某一个时间内同时运行多个程序。
并发:是物理上同时发生,指在某一个时间点同时运行多个程序。
Java程序的运行原理:
由java命令启动JVM,JVM启动就相当于启动一个进程。
接着有该进程创建了一个主线程去调main方法。
方法1:继承Thread实现线程
步骤:
A:自定义类MyThread继承Thread类
B:MyThread类里面重写run()
C:创建对象
D:启动线程
该类为什么重写run()方法? 不是类中所有代码都需要被线程执行的。而这个时候,为了区分哪些代码能够被线程执行,Java提供了run方法来包含被线程执行的代码。
获取线程对象的名称:
public final String getName() :获取线程对象的名称
设置线程对象的名称:
public final void setName()
针对不是Thread类的子类中如何获取线程对象名称
public static Thread currentThread() : 返回当前正在执行的线程对象
Thread.currentThread().getName()
public final void setDaemon(boolean on)将线程设置为守护线程或用户线程
当正在运行的线程都是守护线程时,Java虚拟机退出, 该方法必须在启动前调用
public final void join() ; 等待该线程终止后再调用其它线程
设置线程对象优先级
public final int getPriority() :返回线程对象优先级
public final void setPriority(int ne) : 设置线程优先级
注意:
线程默认优先级是5
线程优先级的范围是 : 1-10
线程优先级高仅表示线程获取的CPU时间片的几率高,需要在次数比较多,或多次运行时效果才比较显著。
IllegalArgumentException:非法参数异常。
抛出的异常表明向方法传递了一个不合法或不正确的参数。
public static void sleep() 线程休眠
线程中断
public final void stop() : 让线程停止,过时了, 超过一定时间,直接结束进程
public final void interrupt() : 中断线程,把线程的状态终止,并抛出一个InterruptedException。
public static void yield() : 暂停当前正在执行的线程,让CPU去执行其它线程
让多个线程执行更和谐
方法二: 实现Runnable接口
步骤 : A:自定义MyRunnable实现Runnable接口
B:重写run()方法
C:创建MyRunnable类的对象
D:创建Thread类的对象,并把c步骤的对象作为构造参数传递
案例:模拟售票
版本1 : 继承Thread类
版本二: 实现Runnable接口
版本三:通过sleep() 暴露出问题
如何解决线程安全问题?
分析哪些原因导致问题:
A: 是否是多线程环境
B: 是否共享数据
C: 是否有多条语句操作共享数据
解决思路:
把多条语句操作共享数据的代码给包成一个整体,让某一个线程在执行的时候,别的线程不能进入。
同步代码块:
synchronized(对象){
需要同步的代码
}
注意: 同步可以解决安全问题的根本原因就在那个对象上,该对象如同锁的功能。
多个线程必须是同一把锁。
版本四:使用synchronized 同步解决问题
同步的好处: 可以解决多线程的安全问题
同步的弊端: 当线程相当多时,因为每个线程都会去判断同步上的锁,
这是很耗资源的,无形中降低了程序运行的效率。
A:同步代码块的锁对象是: 任意对象
B:同步方法的格式及锁对象:
把同步方法关键字加在方法上
同步方法的锁对象是this
C:静态方法及代码块是: 类的字节码对象
将集合变成线程安全
总结:
(1)多线程: 一个应用程序多条执行路径
进程: 正在执行的应用程序
线程: 进程的执行单元,执行路径
单线程: 一个应用程序只有一条执行路径
多线程: 一个应用程序有多条执行路径
多进程的意义: 提高CPU的使用率
多线程的意义: 提高应用程序的使用率
(2)Java程序的运行原理及JVM的启动是多线程的吗?
A:JAVA命令去启动JVM,JVM就会启动一个进程,该进程会启动主线程。
B:JVM的启动是多线程的,因为最低有两个线程启动主线程和垃圾回收线程
(3)多线程实现方案
A:继承Thread类
B:实现Runnable接口
(4)线程的调度和优先级问题
A:线程的调度 a:分时调度 b:抢占式调度(java采用该种)
B:获取和设置线程优先级 a默认是5 b范围是1-10
(5)线程的控制
A:休眠线程 B:加入线程 C:礼让线程 D:后台线程 E:终止线程
(6)线程的生命周期
A:新建 B:就绪 C:运行 D:阻塞 E:死亡
(7)多线程安全问题的原因
A:是否有多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
(8)同步解决线程安全问题
A:同步代码块
synchronized(对象){
需要被同步的代码
}
这里的锁对象可以是任意对象
B:同步方法
把同步加在方法上
这里的锁对象是this
C:静态同步方法
把同步加在方法上
这里的锁对象是当前类的字节码文件对象
(9)回顾以前的线程安全的类
A:StringBuffer
B:Vector
C:Hashtable
D:如何把一个线程不安全的集合类变成一个线程安全的集合类
用Collections工具类的方法即可。
什么是进程?
进程就是正在运行的程序;是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。
多进程有什么意义?
单进程的计算机只能做一件事情,而我们现在的计算机可以做多件事情。
举例:一边玩游戏,一边听音乐等
现在的计算机都支持多进程的,可以在一个时间段内执行多个任务。并且,可以提高CPU使用率。
什么是线程?
在同一个进程内又可以执行多个任务,而每一个任务可以看成是一个线程。
线程:是程序的执行单元,执行路径。是程序使用CPU的最基本单位。
单线程:如果程序只有一条执行路径。
多线程:如果程序有多条执行路径。
多线程有什么意义呢?
多线程的存在,不是提高程序的执行速度。其实是为了提高应用程序的使用率。
程序的执行其实都是在抢CPU的资源,CPU的执行权。
多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的机率抢到CPU的执行权。
我们不敢保证哪一个线程能够在哪个时刻抢到,所以线程执行有随机性。
并行和并发的区别:
并行:是逻辑上同时发生,指在某一个时间内同时运行多个程序。
并发:是物理上同时发生,指在某一个时间点同时运行多个程序。
Java程序的运行原理:
由java命令启动JVM,JVM启动就相当于启动一个进程。
接着有该进程创建了一个主线程去调main方法。
方法1:继承Thread实现线程
步骤:
A:自定义类MyThread继承Thread类
B:MyThread类里面重写run()
C:创建对象
D:启动线程
该类为什么重写run()方法? 不是类中所有代码都需要被线程执行的。而这个时候,为了区分哪些代码能够被线程执行,Java提供了run方法来包含被线程执行的代码。
public class MyThread extends Thread { @Override public void run() { // 一般来说,被线程执行的代码肯定是比较耗时的。 // 所以我们用循环改进 for (int x = 0; x < 200; x++) { System.out.println(x); } } } public class MyThreadDemo { public static void main(String[] args) { // 创建线程对象 // MyThread my = new MyThread(); // // 启动线程 // my.run(); // my.run(); // 调用run()方法为什么是单线程的呢? // 因为run()方法直接调用其实就相当于普通的方法调用,所以你看到的是单线程的效果 // 要想看到多线程的效果,就必须说说另一个方法:start() // 面试题:run()和start()的区别? // run():仅仅是封装被线程执行的代码,直接调用是普通方法 // start():首先启动了线程,然后再由jvm去调用该线程的run()方法。 // MyThread my = new MyThread(); // my.start(); // // IllegalThreadStateException:非法的线程状态异常 // // 为什么呢?因为这个相当于是my线程被调用了两次。而不是两个线程启动。 // my.start(); // 创建两个线程对象 MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); my1.start(); my2.start(); } }
获取线程对象的名称:
public final String getName() :获取线程对象的名称
设置线程对象的名称:
public final void setName()
针对不是Thread类的子类中如何获取线程对象名称
public static Thread currentThread() : 返回当前正在执行的线程对象
Thread.currentThread().getName()
public class MyThreadDemo { public static void main(String[] args) { // 创建线程对象 //无参构造+setXxx() // MyThread my1 = new MyThread(); // MyThread my2 = new MyThread(); // //调用方法设置名称 // my1.setName("林青霞"); // my2.setName("刘意"); // my1.start(); // my2.start(); //带参构造方法给线程起名字 // MyThread my1 = new MyThread("林青霞"); // MyThread my2 = new MyThread("刘意"); // my1.start(); // my2.start(); //我要获取main方法所在的线程对象的名称,该怎么办呢? //遇到这种情况,Thread类提供了一个很好玩的方法: //public static Thread currentThread():返回当前正在执行的线程对象 System.out.println(Thread.currentThread().getName()); } }
public final void setDaemon(boolean on)将线程设置为守护线程或用户线程
当正在运行的线程都是守护线程时,Java虚拟机退出, 该方法必须在启动前调用
public class ThreadDaemon extends Thread { @Override public void run() { for (int x = 0; x < 100; x++) { System.out.println(getName() + ":" + x); } } } public class ThreadDaemonDemo { public static void main(String[] args) { ThreadDaemon td1 = new ThreadDaemon(); ThreadDaemon td2 = new ThreadDaemon(); td1.setName("关羽"); td2.setName("张飞"); // 设置守护线程 td1.setDaemon(true); td2.setDaemon(true); td1.start(); td2.start(); Thread.currentThread().setName("刘备"); for (int x = 0; x < 5; x++) { System.out.println(Thread.currentThread().getName() + ":" + x); } } }
public final void join() ; 等待该线程终止后再调用其它线程
public class ThreadJoinDemo { public static void main(String[] args) { ThreadJoin tj1 = new ThreadJoin(); ThreadJoin tj2 = new ThreadJoin(); ThreadJoin tj3 = new ThreadJoin(); tj1.setName("李渊"); tj2.setName("李世民"); tj3.setName("李元霸"); tj1.start(); try { tj1.join(); } catch (InterruptedException e) { e.printStackTrace(); } tj2.start(); tj3.start(); } }
设置线程对象优先级
public final int getPriority() :返回线程对象优先级
public final void setPriority(int ne) : 设置线程优先级
注意:
线程默认优先级是5
线程优先级的范围是 : 1-10
线程优先级高仅表示线程获取的CPU时间片的几率高,需要在次数比较多,或多次运行时效果才比较显著。
IllegalArgumentException:非法参数异常。
抛出的异常表明向方法传递了一个不合法或不正确的参数。
public class ThreadPriority extends Thread { @Override public void run() { for (int x = 0; x < 100; x++) { System.out.println(getName() + ":" + x); } } } public class ThreadPriorityDemo { public static void main(String[] args) { ThreadPriority tp1 = new ThreadPriority(); ThreadPriority tp2 = new ThreadPriority(); ThreadPriority tp3 = new ThreadPriority(); tp1.setName("东方不败"); tp2.setName("岳不群"); tp3.setName("林平之"); // 获取默认优先级 // System.out.println(tp1.getPriority()); // System.out.println(tp2.getPriority()); // System.out.println(tp3.getPriority()); // 设置线程优先级 // tp1.setPriority(100000); //设置正确的线程优先级 tp1.setPriority(10); tp2.setPriority(1); tp1.start(); tp2.start(); tp3.start(); } }
public static void sleep() 线程休眠
public class ThreadSleep extends Thread { @Override public void run() { for (int x = 0; x < 100; x++) { System.out.println(getName() + ":" + x + ",日期:" + new Date()); // 睡眠 // 困了,我稍微休息1秒钟 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class ThreadSleepDemo { public static void main(String[] args) { ThreadSleep ts1 = new ThreadSleep(); ThreadSleep ts2 = new ThreadSleep(); ThreadSleep ts3 = new ThreadSleep(); ts1.setName("林青霞"); ts2.setName("林志玲"); ts3.setName("林志颖"); ts1.start(); ts2.start(); ts3.start(); } }
线程中断
public final void stop() : 让线程停止,过时了, 超过一定时间,直接结束进程
public final void interrupt() : 中断线程,把线程的状态终止,并抛出一个InterruptedException。
public class ThreadStop extends Thread { @Override public void run() { System.out.println("开始执行:" + new Date()); // 我要休息10秒钟,亲,不要打扰我哦 try { Thread.sleep(10000); } catch (InterruptedException e) { // e.printStackTrace(); System.out.println("线程被终止了"); } System.out.println("结束执行:" + new Date()); } } public class ThreadStopDemo { public static void main(String[] args) { ThreadStop ts = new ThreadStop(); ts.start(); // 你超过三秒不醒过来, try { Thread.sleep(3000); // ts.stop(); // 结束线程 ts.interrupt(); //抛出异常,将线程状态终止 } catch (InterruptedException e) { e.printStackTrace(); } } }
public static void yield() : 暂停当前正在执行的线程,让CPU去执行其它线程
让多个线程执行更和谐
public class ThreadYield extends Thread { @Override public void run() { for (int x = 0; x < 100; x++) { System.out.println(getName() + ":" + x); Thread.yield(); } } } public class ThreadYieldDemo { public static void main(String[] args) { ThreadYield ty1 = new ThreadYield(); ThreadYield ty2 = new ThreadYield(); ty1.setName("林青霞"); ty2.setName("刘意"); ty1.start(); ty2.start(); } }
方法二: 实现Runnable接口
步骤 : A:自定义MyRunnable实现Runnable接口
B:重写run()方法
C:创建MyRunnable类的对象
D:创建Thread类的对象,并把c步骤的对象作为构造参数传递
public class MyRunnable implements Runnable { @Override public void run() { for (int x = 0; x < 100; x++) { // 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用 System.out.println(Thread.currentThread().getName() + ":" + x); } } } public class MyRunnableDemo { public static void main(String[] args) { // 创建MyRunnable类的对象 MyRunnable my = new MyRunnable(); // 创建Thread类的对象,并把C步骤的对象作为构造参数传递 // Thread(Runnable target) // Thread t1 = new Thread(my); // Thread t2 = new Thread(my); // t1.setName("林青霞"); // t2.setName("刘意"); // Thread(Runnable target, String name) Thread t1 = new Thread(my, "林青霞"); Thread t2 = new Thread(my, "刘意"); t1.start(); t2.start(); } }
案例:模拟售票
版本1 : 继承Thread类
public class SellTicket extends Thread { // 定义100张票 // private int tickets = 100; // 为了让多个线程对象共享这100张票,我们其实应该用静态修饰 private static int tickets = 100; @Override public void run() { // 定义100张票 // 每个线程进来都会走这里,这样的话,每个线程对象相当于买的是自己的那100张票,这不合理,所以应该定义到外面 // int tickets = 100; // 是为了模拟一直有票 while (true) { if (tickets > 0) { System.out.println(getName() + "正在出售第" + (tickets--) + "张票"); } } } } public class SellTicketDemo { public static void main(String[] args) { // 创建三个线程对象 SellTicket st1 = new SellTicket(); SellTicket st2 = new SellTicket(); SellTicket st3 = new SellTicket(); // 给线程对象起名字 st1.setName("窗口1"); st2.setName("窗口2"); st3.setName("窗口3"); // 启动线程 st1.start(); st2.start(); st3.start(); } }
版本二: 实现Runnable接口
public class SellTicket implements Runnable { // 定义100张票 private int tickets = 100; @Override public void run() { while (true) { if (tickets > 0) { System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } } } public class SellTicketDemo { public static void main(String[] args) { // 创建资源对象 SellTicket st = new SellTicket(); // 创建三个线程对象 Thread t1 = new Thread(st, "窗口1"); Thread t2 = new Thread(st, "窗口2"); Thread t3 = new Thread(st, "窗口3"); // 启动线程 t1.start(); t2.start(); t3.start(); } }
版本三:通过sleep() 暴露出问题
public class SellTicket implements Runnable { // 定义100张票 private int tickets = 100; // @Override // public void run() { // while (true) { // // t1,t2,t3三个线程 // // 这一次的tickets = 100; // if (tickets > 0) { // // 为了模拟更真实的场景,我们稍作休息 // try { // Thread.sleep(100); // t1就稍作休息,t2就稍作休息 // } catch (InterruptedException e) { // e.printStackTrace(); // } // // System.out.println(Thread.currentThread().getName() + "正在出售第" // + (tickets--) + "张票"); // // 理想状态: // // 窗口1正在出售第100张票 // // 窗口2正在出售第99张票 // // 但是呢? // // CPU的每一次执行必须是一个原子性(最简单基本的)的操作。 // // 先记录以前的值 // // 接着把ticket-- // // 然后输出以前的值(t2来了) // // ticket的值就变成了99 // // 窗口1正在出售第100张票 // // 窗口2正在出售第100张票 // // } // } // } @Override public void run() { while (true) { // t1,t2,t3三个线程 // 这一次的tickets = 1; if (tickets > 0) { // 为了模拟更真实的场景,我们稍作休息 try { Thread.sleep(100); //t1进来了并休息,t2进来了并休息,t3进来了并休息, } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); //窗口1正在出售第1张票,tickets=0 //窗口2正在出售第0张票,tickets=-1 //窗口3正在出售第-1张票,tickets=-2 } } } } /* * 实现Runnable接口的方式实现 * * 通过加入延迟后,就产生了连个问题: * A:相同的票卖了多次 * CPU的一次操作必须是原子性的 * B:出现了负数票 * 随机性和延迟导致的 */ public class SellTicketDemo { public static void main(String[] args) { // 创建资源对象 SellTicket st = new SellTicket(); // 创建三个线程对象 Thread t1 = new Thread(st, "窗口1"); Thread t2 = new Thread(st, "窗口2"); Thread t3 = new Thread(st, "窗口3"); // 启动线程 t1.start(); t2.start(); t3.start(); } }
如何解决线程安全问题?
分析哪些原因导致问题:
A: 是否是多线程环境
B: 是否共享数据
C: 是否有多条语句操作共享数据
解决思路:
把多条语句操作共享数据的代码给包成一个整体,让某一个线程在执行的时候,别的线程不能进入。
同步代码块:
synchronized(对象){
需要同步的代码
}
注意: 同步可以解决安全问题的根本原因就在那个对象上,该对象如同锁的功能。
多个线程必须是同一把锁。
版本四:使用synchronized 同步解决问题
public class SellTicket implements Runnable { // 定义100张票 private int tickets = 100; //创建锁对象 private Object obj = new Object(); // @Override // public void run() { // while (true) { // synchronized(new Object()){ // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() + "正在出售第" // + (tickets--) + "张票"); // } // } // } // } @Override public void run() { while (true) { synchronized (obj) { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } } } } public class SellTicketDemo { public static void main(String[] args) { // 创建资源对象 SellTicket st = new SellTicket(); // 创建三个线程对象 Thread t1 = new Thread(st, "窗口1"); Thread t2 = new Thread(st, "窗口2"); Thread t3 = new Thread(st, "窗口3"); // 启动线程 t1.start(); t2.start(); t3.start(); } }
同步的好处: 可以解决多线程的安全问题
同步的弊端: 当线程相当多时,因为每个线程都会去判断同步上的锁,
这是很耗资源的,无形中降低了程序运行的效率。
A:同步代码块的锁对象是: 任意对象
B:同步方法的格式及锁对象:
把同步方法关键字加在方法上
同步方法的锁对象是this
C:静态方法及代码块是: 类的字节码对象
public class SellTicket implements Runnable { // 定义100张票 private static int tickets = 100; // 定义同一把锁 private Object obj = new Object(); private Demo d = new Demo(); private int x = 0; //同步代码块用obj做锁 // @Override // public void run() { // while (true) { // synchronized (obj) { // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() // + "正在出售第" + (tickets--) + "张票 "); // } // } // } // } //同步代码块用任意对象做锁 // @Override // public void run() { // while (true) { // synchronized (d) { // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() // + "正在出售第" + (tickets--) + "张票 "); // } // } // } // } @Override public void run() { while (true) { if(x%2==0){ synchronized (SellTicket.class) { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 "); } } }else { // synchronized (d) { // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() // + "正在出售第" + (tickets--) + "张票 "); // } // } sellTicket(); } x++; } } // private void sellTicket() { // synchronized (d) { // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() // + "正在出售第" + (tickets--) + "张票 "); // } // } // } //如果一个方法一进去就看到了代码被同步了,那么我就再想能不能把这个同步加在方法上呢? // private synchronized void sellTicket() { // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() // + "正在出售第" + (tickets--) + "张票 "); // } // } private static synchronized void sellTicket() { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 "); } } } class Demo { } public class SellTicketDemo { public static void main(String[] args) { // 创建资源对象 SellTicket st = new SellTicket(); // 创建三个线程对象 Thread t1 = new Thread(st, "窗口1"); Thread t2 = new Thread(st, "窗口2"); Thread t3 = new Thread(st, "窗口3"); // 启动线程 t1.start(); t2.start(); t3.start(); } }
将集合变成线程安全
public class ThreadDemo { public static void main(String[] args) { // 线程安全的类 StringBuffer sb = new StringBuffer(); Vector<String> v = new Vector<String>(); Hashtable<String, String> h = new Hashtable<String, String>(); // Vector是线程安全的时候才去考虑使用的,但是我还说过即使要安全,我也不用你 // 那么到底用谁呢? // public static <T> List<T> synchronizedList(List<T> list) List<String> list1 = new ArrayList<String>();// 线程不安全 List<String> list2 = Collections .synchronizedList(new ArrayList<String>()); // 线程安全 } }
总结:
(1)多线程: 一个应用程序多条执行路径
进程: 正在执行的应用程序
线程: 进程的执行单元,执行路径
单线程: 一个应用程序只有一条执行路径
多线程: 一个应用程序有多条执行路径
多进程的意义: 提高CPU的使用率
多线程的意义: 提高应用程序的使用率
(2)Java程序的运行原理及JVM的启动是多线程的吗?
A:JAVA命令去启动JVM,JVM就会启动一个进程,该进程会启动主线程。
B:JVM的启动是多线程的,因为最低有两个线程启动主线程和垃圾回收线程
(3)多线程实现方案
A:继承Thread类
B:实现Runnable接口
(4)线程的调度和优先级问题
A:线程的调度 a:分时调度 b:抢占式调度(java采用该种)
B:获取和设置线程优先级 a默认是5 b范围是1-10
(5)线程的控制
A:休眠线程 B:加入线程 C:礼让线程 D:后台线程 E:终止线程
(6)线程的生命周期
A:新建 B:就绪 C:运行 D:阻塞 E:死亡
(7)多线程安全问题的原因
A:是否有多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
(8)同步解决线程安全问题
A:同步代码块
synchronized(对象){
需要被同步的代码
}
这里的锁对象可以是任意对象
B:同步方法
把同步加在方法上
这里的锁对象是this
C:静态同步方法
把同步加在方法上
这里的锁对象是当前类的字节码文件对象
(9)回顾以前的线程安全的类
A:StringBuffer
B:Vector
C:Hashtable
D:如何把一个线程不安全的集合类变成一个线程安全的集合类
用Collections工具类的方法即可。
发表评论
-
深入Java虚拟机学习----Java内存区域01
2016-02-14 15:20 543java虚拟机运行时数据区域 1、程序计数器 ... -
java排序算法
2016-01-07 15:38 571对于一个排序算法来说,一般从3个方面来衡量算法的优劣。 1、 ... -
java类成员初始化顺序
2015-12-29 16:33 746一个类中,最首先被初始化的是静态成员。只要一个类创建对象或调用 ... -
java jdbc实现
2015-12-29 16:05 707JDBC连接数据库 public class Tes ... -
Java垃圾回收机制
2015-12-29 09:32 638Java虚拟机中堆的实现有点像一个传送带,每分配一个对象,它就 ... -
动态生成验证码
2015-11-03 10:03 4851、创建图片缓冲区 2、设置其宽高 3、得到这个图片的绘制环境 ... -
I/O输入输出流总结
2015-10-26 23:03 613JavaI/O流 InputStream / OutputS ... -
传智播客风清扬视频-------网络编程简介
2015-10-12 16:08 1041计算机网络模型 ... -
传智播客风清扬视频-------线程简介2
2015-10-10 09:40 732为了更清晰的表达如何加锁和释放锁,JDK1.5以后提供了一个新 ... -
javaIO练习之简单用户登录系统
2015-09-29 10:43 717package com.iouser.pojo; p ... -
传智播客风清扬视频-------IO简述之字符流常用实现类
2015-09-28 15:11 749字符编码: String(byte[] bytes,Stri ... -
传智播客风清扬视频-------IO简述之InputStream和OutputStream及常实现类
2015-09-24 23:09 2460IO流的分类: 流向: 输入流 ... -
传智播客风清扬视频-------IO简述之File讲解
2015-09-24 15:15 1167File类概述和构造方法 ... -
疯狂java基础功16讲(2)------对象与内存控制
2016-01-15 10:39 702Java内存管理分为两个方面:内存分配和内存回收。 内存分配特 ... -
传智播客风清扬视频------异常简述
2015-09-23 15:38 598一、异常初识 异常: ... -
疯狂java基本功16讲(1)----数组与内存控制
2015-09-23 10:00 767重点讲述问题: (1)、Java数组在内存分配方面的知识 ...
相关推荐
在"传智播客 刘意-2015年Java基础视频-深入浅出精华版 笔记day01-day27"这套课程中,Java初学者将踏上一段全面而深入的Java编程之旅。刘意老师以其丰富的教学经验,将复杂的Java知识讲解得通俗易懂,旨在帮助学员...
传智播客风清扬老师的Java基础教程,包括课堂笔记 和课后练习。帮助初学者快速上手,
"传智播客_Andorid_Android基础视频video_第四天修"这个压缩包显然包含了针对Android初学者的第四天教学内容,旨在帮助学习者深化对Android开发的理解。传智播客是一家知名的教育机构,他们的课程通常覆盖了广泛的IT...
#### Java语言简介 - **平台版本**:Java拥有三个主要版本: - J2SE(Standard Edition):标准版,适用于桌面应用程序开发。 - J2ME(Micro Edition):小型版,适用于嵌入式设备和移动设备。 - J2EE...
传智播客刘意-风清扬的JavaSE学习资料,共有27天,视频和源码都有,下载后打开记事本复制链接密码,下载即可
风清扬输入法是一款专为中文用户设计的输入工具,旨在提供高效、便捷的汉字输入体验。这款输入法以其独特的特点和创新的功能,在众多输入法软件中脱颖而出,深受用户喜爱。下面将详细介绍风清扬输入法的核心功能和...
本次讲座由风清扬老师主讲,讲座已经成功举办了四次,并且受到了广泛的好评。为了让更多的人能够学习到SEO的知识,讲座内容被整理成了PDF文件供免费下载。本次讲座得到了红杉树(中国)信息技术有限公司提供的视频...
风清扬五笔自造词维护风清扬五笔自造词维护风清扬五笔自造词维护风清扬五笔自造词维护风清扬五笔自造词维护风清扬五笔自造词维护风清扬五笔自造词维护风清扬五笔自造词维护风清扬五笔自造词维护风清扬五笔自造词维护...
风清扬简繁体五笔输入法是一款专为中文用户设计的输入工具,它结合了简体和繁体汉字的编码,旨在提供高效、便捷的文字输入体验。在深入理解这款输入法之前,我们首先需要了解五笔字型的基本概念。 五笔字型是一种...
繁体五笔输入法:风清扬五笔输入法 繁体五笔输入法:风清扬五笔输入法
风清扬简转繁,好用
在IT领域,多线程编程是一项重要的技术,特别是在C++这样的高级编程语言中。Qt5框架为开发者提供了丰富的工具和接口来实现多线程,使得应用程序能够同时执行多个任务,提高程序的执行效率和响应性。本文将深入探讨Qt...
"风清扬繁简两用五笔输入法"是一款专为中文输入设计的软件,尤其适合需要在繁体和简体中文之间切换的用户。它整合了广东话打法,拓展了传统五笔输入法的功能,增加了对粤语常用词汇的支持,同时也保留了对“老字”...
风清扬繁简两用五笔输入法6.6版是一款专为中文用户设计的高效汉字输入工具,尤其适用于那些需要在繁体和简体汉字间切换的用户。这款输入法软件具有高度的兼容性和稳定性,它特别指出支持Windows Vista操作系统,意味...
《多线程俄罗斯方块:探索C# Winform与并发编程》 在计算机科学领域,游戏开发是一项技术密集型的任务,而"多线程俄罗斯方块"是一个巧妙地结合了Winform用户界面、多线程编程、委托和事件处理机制的实例。这个项目...
《创业计划书-汽车服务创业计划书(风清扬)》是针对汽车服务业的一份详尽的商业规划文档,旨在为潜在的创业者提供一个清晰的框架,指导他们如何在这个行业中成功起步并发展业务。这份计划书的核心内容可能涵盖以下几...
《风清扬五笔》是一款深受用户喜爱的五笔输入法软件,它的出现极大地提高了中文输入的效率。作为一款高效、精准的输入工具,风清扬五笔在设计上注重用户体验,结合了传统五笔字型的优势,同时进行了创新与优化,使其...
风清扬简繁五笔输入法6.91是一款专为中文输入设计的软件,它融合了简体和繁体字的输入功能,为用户提供了一种高效、便捷的文字输入方式。这款输入法由风清扬团队开发,因其易用性和高效率而受到用户的喜爱。 在...
风清扬输入法是一款以武侠人物“风清扬”命名的汉字输入法,它旨在提供高效、便捷的中文输入体验。这款旧版的风清扬输入法可能包含了一些早期的功能特性和用户界面设计,对于那些熟悉旧有操作习惯或者喜欢经典界面的...
帶简繁体输入法 风清扬输入法 帶简繁体输入法 风清扬输入法