1.关于进程和线程的理解
进程:正在执行的应用程序
线程:进程的执行单元,执行路径
单线程:一个应用程序只有一条执行路径
多线程:一个应用程序有多条执行路径
多进程的意义:在于一高CPU的使用率
多进程的意义:在于提高应用程序的使用率
2.Java程序的运行原理
有Java命令启动JVM,JVM启动则相当于启动了一个进程
之后由该进程创建一个主线程去调用main方法
3.JVM的启动是否是多线程?
为防止出现内存溢出的情况,JVM启动的时候会同时启动垃圾回收线程
加上主线程,则JVM启动时最少有两个线程启动,由此可知JVM启动时多线程。
4.run()和start()的区别
run():仅仅是封装了背线程执行的代码,直接调用时普通方法。
start():首先启动了线程,然后再由JVM去调用该线程的run()方法。
5.多线程的实现方式一:继承Thread类,重写run()方法
A:常用功能
public final String getName():获取线程的名称
public final void setName(String name):设置线程的名称(也可用带参构造方法为线程设置名称)
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 newPriority):设置线程的优先级
注意:线程优先级的范围是1-10,默认为5.线程优先级高仅仅代表线程获取的CPU时间片的几率高
public static void sleep(long millis):线程休眠
public final void stop():线程停止,该方法已过时,但仍然可以使用
public void interrupt():中断线程,终止线程状态,并抛出一个InterruptedException异常
public static void yield():暂停当前正在执行的线程对象,并执行其他线程
注意:该方法可以让线程执行更加和谐,但无法保证一人一次的执行。
B:电影院三窗口售票案例方式一实现
public class SellTicket extends Thread{
private static int tickets = 100;
public void run(){
while(true){
if(tickets > 0){
System.out.println(getName() + "正在出售第" + (tickets--) + "张票")
}
}
}
}
public class SellTicketDemo{
public static void main(String[] args){
SellTicket st1 = new SellTicket();
SellTicket st1 = new SellTicket();
SellTicket st1 = new SellTicket();
st1.setName("窗口1");
st2.setName("窗口2");
st3.setName("窗口3");
st1.start();
st2.start();
st3.start();
}
}
6.多线程的实现方法二:实现Runnable接口,重写run()方法。
A:电影院三窗口售票案例方式二实现
public class SellTicket implements Runnable{
private int tickets = 100;
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();
}
}
7.线程生命周期
A:新建
B:就绪
C:运行
D:阻塞
E:死亡
8.线程安全问题
A:判断多线程是否会出现安全问题的依据
a:是否是多线程环境
b:是否有共享数据
c:是否有多天语句操作共享数据
B:在设置了线程休眠之后,出现了同票和负票问题。
同票原因:CPU的每一次执行是一个原子性(最简单的)操作。
负票原因:线程随机性和延迟导致了负票。
9.加锁解决线程安全问题
同步的好处:解决了线程安全问题
同步的弊端:每个线程都需要判断同步上锁的状态,降低了运行效率且容易产生死锁
A:同步代码块(锁对象可以为任意对象)
public class SellTicket implements Runnable{
private int tickets = 100;
private Object obj = new Object();
public void run(){
while(true){
synchronized(obj){
if(tickets > 0){
try{
Thread.sleep(1000);
}chtch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName +
"正在出售第" + (tickets--) + "张票");
}
}
}
}
}
B:同步方法(锁对象时this)
public class SellTicket implements Runnable{
private int tickets = 100;
public void run(){
while(true){
sellTicket();
}
}
public synchronized void sellTicket(){
if(tickets > 0){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +
"正在出售第" + (tickets--) + "张票");
}
}
}
C:静态同步方法(锁对象时当前类的字节码文件对象)
与同步方法不同的地方在于:方法申明中多了静态修饰符:static
public static synchronized void sellTicket(){}
10. 使用锁对象Lock解决线程安全问题
A:ReentrantLock是Lock的实现类
B:常用方法
void lock():获取锁
void unlock():释放锁
C:解决电影票问题
public class SellTicket() implements Runnable{
private int stckets = 100;
private Lock lock = new ReenTrantLock();
public void run(){
while(true){
try{
lock.lock();
if(tickets > 0){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +
"正在出售第" + (tickets--) + "张票");
}
}finally{
lock.unlock();
}
}
}
}
11.死锁问题
A:死锁
两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象
B:代码演示
public class MyLock{
//创建两个锁对象
public static final Object objA = new Object();
public static final Object objA = new Object();
}
public class DieLock extends Thread{
private boolean flag;
public DieLock(boolean flag){
this.flag = flag;
}
public void run(){
if(flag){
synchronized(MyLock.objA){
System.out.println("if objA");
synchornized(MyLock.objB){
System.out.println("if objB");
}
}
}else{
synchornized(MyLock.objB){
System.out.println("else objB");
synchornized(Mylock.objA){
System.out.println("else objA");
}
}
}
}
}
public class DieLockDemo{
public static void main(String[] args){
DieLock dl1 = new DieLock(true);
DieLock dl2 = new DieLock(false);
dl1.start();
dl2.start();
}
} |
|