一、程序和进程:java
程序:一个固定的运算逻辑和数据的集合,是一个静态的状态,通常存储在硬盘中安全
进程:正在运行的程序,是程序的一次运行,是一个动态的状态多线程
二、进程和线程:并发
进程:一个正在运行的程序,有本身独立的资源分配,是一个独立的个体ide
线程:一个独立的执行路径。多线程,一个进程中可能有许多子任务,每一个线程均可以独立的完成一个子任务,各个任务之间没有依赖关系,能够单独执行。this
三、并行和并发:spa
并行:多个程序同时执行,相互独立。线程
并发:多个任务同时发起,但不能同时执行,只能来回切换的执行。在同一个时间段内,将每一个程序都执行过。设计
问题:并发究竟是提高了效率仍是下降了效率?code
多个任务都在执行,效率提升了,但对于某一单独任务来讲是下降了。
并发技术解决了各个设备之间速率不一样的问题(如内存和硬盘的存储速度不一样),大大提升了CPU的利用率。
四、多线程实现方式(3种):
继承方式:(代码示例)
- 写一个类,继承Thread
- 重写run()方法
- 建立类对象,对象.start()方法执行
注:若使用对象.run(),则是普通的执行方法,不会开启新线程
实现方式:(代码示例)
- 写一个类,实现Runnable接口
- 重写run()方法
- 建立类对象(任务对象)
- 建立线程对象,将任务传给线程Thread t = new Thread(任务对象名);
- t.start()启动线程,会自动执行run()内容
两种方式的比较:
- 代码复杂程度:第一种方式更简单
- 实现原理
继承Thread,调用start()方法,本质上是调用start0()方法,是本地方法,由C语言实现,java中看不到源代码
实现Runnable接口,是建立了一个任务对象,将对象传给线程,再开启线程
3.在设计实用性方面:
java中继承都是单继承,若是继承了Thread,则没法继承其它类
Java中对接口的实现能够多实现,不影响程序的编写
匿名内部类实现方式:(代码示例)
new Thread(){run () { } }.start();
new Thread(new Runnable(){run () {} });
五、多线程中的经常使用方法:(代码示例)
1.获取线程的名称getName()
注意:
1.若是没有给线程命名,则线程名字从Thread-0开始依次增长
2.可使用对象的引用调用此方法,也能够在线程类中调用
Thread.currentThread().getName()
3.Runnable实现类中没有此方法
2.使用对象的引用设置线程名字setName():
构造方法也可设置线程名字:Thread(Runnable 任务名, String 线程名);
对象名.setName(String name)
3.获取当前线程对象Thread.currentThread()
4.线程休眠Thread.sleep(毫秒)
做用:当代码在某个位置须要休息时,就使用休眠
不管哪一个线程执行到这里都会休眠
注意:有一个异常,中断异常InterruptedException,在run()中必须处理,不能声明
5.守护线程:setDaemon(boolean flag)
每条线程默认都不是守护线程,只有设定flag为true才会成为守护线程
特色:守护其它非守护线程,若是其它非守护线程全都挂掉则跟随死亡
6.设置线程的优先级setPriority()
NORM_PRIORITY 5
MAX_PRIORITY 10
MIN_PRIORITY 1
六、安全问题(同步)(代码示例:火车站购票)
多线程在操做共享数据的时候可能会产生线程不安全问题
解决方法:使用同步代码块
格式:synchronized(锁对象){须要同步的代码}
原理:在有线程处于同步代码块之中时,其它线程必须在代码块外等待,直到里面的线程运行结束
同步方法:当一个方法中全部的代码都在同步代码块中时,能够将方法定义为同步方法
格式:权限修饰符 synchronized 返回值类型 方法名(参数列表){方法体};
注:非静态方法的锁对象是this,也就是当前对象
静态方法的锁对象是 类名.class (在方法区的一个对象)
若是两条线程操做相同的数据,锁对象必须保持一致
使用什么锁,通常用保护的数据做为锁对象
七、死锁
A线程须要甲资源,同时拥有了乙资源,B线程拥有乙资源,同时须要甲资源,两条线程都不愿释放本身的资源,就会造成死锁。
有了同步代码块的嵌套,就可能发生死锁。某条线程获取了外层的锁对象A,须要内层的锁对象B,等待;另一条线程获取了外层的锁对象B,须要内层的锁对象A,等待。两条线程就会造成死锁。


public class Demo01 { //第一种方式:继承Thread,重写run方法,建立对象,对象.start() public static void main(String[] args) { SellTicket st = new SellTicket(); SellTicket st1 = new SellTicket(); SellTicket st2 = new SellTicket(); st.start(); st1.start(); st2.start(); } } class SellTicket extends Thread{ static int count=100;//使用静态属性共享票数 @Override public void run() { while(true){ if(count>0) { System.out.println(this.getName()); String name = Thread.currentThread().getName(); System.out.println(name+"...卖出了第"+count--+"张票"); }else { break; } } } }


public class Demo02 { //第二种方式:实现Runnable接口,重写run方法,建立类对象(任务对象) //建立线程对象并将任务对象传给线程,线程对象.start()启动 public static void main(String[] args) { MyTicket mt = new MyTicket(); Thread t1 = new Thread(mt,"窗口1"); Thread t2 = new Thread(mt,"窗口2"); Thread t3 = new Thread(mt,"窗口3"); t1.start(); t2.start(); t3.start(); } } class MyTicket implements Runnable{ int count = 100; @Override public void run() { while(true){ if(count>0) { String name = Thread.currentThread().getName(); System.out.println(name+"...卖出了第"+count--+"张票"); }else { break; } } } }


public class Demo03 { //第三种方式:匿名内部类 public static void main(String[] args) { new Thread(new MyTicketWindow()).start(); new Thread(new MyTicketWindow()).start(); new Thread(new MyTicketWindow()).start(); } } class MyTicketWindow implements Runnable{ static int count = 100; static Object obj = new Object(); @Override public void run() { while(true){ synchronized (obj) { if(count>0) { try { Thread.sleep(200); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } String name = Thread.currentThread().getName(); System.out.println(name+"...卖出了第"+count--+"张票"); }else { break; } } } } }