1.进程 :
(一)正在执行的程序称作为一个进程。 进程负责了内存空间的划分。
(二)问题: windows号称是多任务的操作系统,那么windows是同时运行多个应用程序吗?
从宏观的角度: windows确实是在同时运行多个应用程序。
从微观角度: cpu是做了一个快速切换执行的动作,由于速度态度,所以我感觉不到在切换 而已。
2.线程:
线程的优先级默认是5;
(一)线程在一个进程 中负责了代码的执行,就是进程中一个执行路径,
(二)多线程: 在一个进程中有多个线程同时在执行不同的任务。
(三)提问 :a.代码的执行是线程负责的,那么他的执行过程?
运行任何一个java程序,jvm在运行的时候都会创建一个main线程执行main方法中所有代码。
b.一个java应用程序至少有几个线程?
至少有两个线程, 一个是主线程负责main方法代码的执行,一个是垃圾回收器线程,负责了回收垃圾。
(四)多线程的好处:
1.解决了一个进程能同时执行多个任务的问题。
2. 提高了资源的利用率。
(五)多线程 的弊端:
1. 增加cpu的负担。
2. 降低了一个进程中线程的执行概率。
3. 引发了线程安全 问题。
4. 出现了死锁现象。
(六)如何创建多线程:
a.创建线程的方式:
方式一:
1. 自定义一个类继承Thread类。
2. 重写Thread类的run方法 , 把自定义线程的任务代码写在run方法中
疑问: 重写run方法的目的是什么?
每个线程都有自己的任务代码,jvm创建的主线程的任务代码就是main方法中的所有代码, 自定义 线程的任务代码就写在run方法中,自定义线程负责了run方法中代码。
3. 创建Thread的子类对象,并且调用start方法开启线程。
注意:一个线程一旦开启,那么线程就会执行run方法中的代码,run方法千万不能直接调用,直接调用 run方法就相当调用了一个普通的方法而已并没有开启新的线程。
方式二:推荐用这个因为java是单继承,多实现的;这就比较好了
1.自定义类实现Runnable接口的run方法
2.再通过创建Thread对象将实现Runable接口类作为实参传给Thread
3.线程在start()即可
public class test04 implements Runnable{ public static void main(String[] args) { // TODO Auto-generated method stub test04 t=new test04(); Thread b=new Thread(t,"小平"); b.start(); for(int i = 0 ; i < 10 ; i++){ System.out.println(Thread.currentThread().getName()+":"+i); } } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<10;i++){ System.out.println(Thread.currentThread().getName()+":"+i); } } }
(七)创建多线程例子
public class MyThread extends Thread{ @override//重写Thread的run方法,再调用这个自定义的线程 public void run(){ for(int i=0;i<10;i++){ System.out.println("自定义线程:"+i); } } public static void main(String[] args){ //创建自定义的线程类 Demo d=new Demo(); //调用start方法启用线程,不能通过d.run()方法调用,这样没有启动线程 d.start(); for(int i=0;i<10;i++){ System.out.println("主线程:"+i); } } }
(八)线程安全(很重要)
a.多线程售票,出现几个线程一起到达莫个位置出现的问题这就是线程安全问题
b.解决办法:出现线程安全原理是多个线程同时访问代码块内部不该同时访问的位置,我们让那部分代码成为一个 整 体一次只能给一个线程访问,就解决问题了
出现线程安全问题的根本原因:
1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。
2. 有多个语句操作了共享资源
方式一:同步代码块
synchronized(锁对象){
需要被同步的代码...
}
注意:1.任意一个对象都可以作为锁对象
原因:任意对象都可作为一个锁对象, 因为凡是对象内部都维护了一个状态,
Java的同步机制,就是将对象中的状态作为锁的标识
state=0:开;1关
2.在同步代码块中调用sleep方法并不是释放对象
3.只有真正需要同步代码块时,否则会降低效率
4.多线程操作的锁对象,必须是唯一共享,否则无效
c.例子:一个银行账户5000块,两夫妻一个拿着 存折,一个拿着卡,开始取钱比赛,每次只能取一千块,要求不准 出现线程安全问题。
class SaleTicket extends Thread{ static int num = 50;//票数 非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。 static Object o = new Object(); public SaleTicket(String name) { super(name); } @Override public void run() { while(true){ //同步代码块 synchronized ("锁") { if(num>0){ System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } num--; }else{ System.out.println("售罄了.."); break; } } } } } public class Demo4 { public static void main(String[] args) { //创建三个线程对象,模拟三个窗口 SaleTicket thread1 = new SaleTicket("窗口1"); SaleTicket thread2 = new SaleTicket("窗口2"); SaleTicket thread3 = new SaleTicket("窗口3"); //开启线程售票 thread1.start(); thread2.start(); thread3.start(); } }
3.死锁
经典的“哲学家就餐问题”,5个哲学家吃中餐,坐在圆卓子旁。每人有5根筷子(不是5双),每两个人中间放一根,哲学家时而思考,时而进餐。每个人都需要一双筷子才能吃到东西,吃完后将筷子放回原处继续思考,如果每个人都立刻抓住自己左边的筷子,然后等待右边的筷子空出来,同时又不放下已经拿到的筷子,这样每个人都无法得到1双筷子,无法吃饭都会饿死,这种情况就会产生死锁:每个人都拥有其他人需要的资源,同时又等待其他人拥有的资源,并且每个人在获得所有需要的资源之前都不会放弃已经拥有的资源。
(一):当多个线程完成功能需要同时获取多个共享资源的时候可能会导致死锁
(二):死锁没有解决办法,只能尽量避免