多线程
多线程
1.了解
1.首先了解一下什么是进程:
进程我理解的就是一个能够独立运行的程序就是一个进程。所有的进程都是由操作系统分配给CPU执行,某个时间点只能执行一个进程,由于CPU执行的速度很快,所以就会感觉到多进程执行
2.进程与线程的关系:
一个进程至少有两个或两个以上的线程 main线程,JVM的GC 垃圾回收机制
例如:电脑管家 (进程) 里面的垃圾清理(线程)、闪电杀毒(线程)。。。。
2.线程
1.特征:
1.每个线程都是独立的,可以并发执行
2.有一定的动态性
3.有一定的不可把控性
2.线程创建的两种方式:
1.继承Thread类并重写run()方法,在run()方法中写入要实现多线程的代码
创建自定义线程类对象,调用start方法,开启线程
2.实现implements Runnable接口,重写run()方法写入要实现多线程的代码
创建Thread类对象,把遵从Runnable 接口的实现类对象,作为Thread类构造方法的参数,使用Thread类中的start() 方法开启线程
3.以上两种方式更推荐使用第二种方式,原因:
1.java有一种特征就是单继承,也就是说你一个类一旦继承Thread类就没有办法继承其他的类,有一定的局限性
2.在处理共享资源方面,第二种方式处理的会更好,能够很好的把线程同程序代码和数据有效的分离
4.后台线程(守护线程):
如果一个进程只有后台线程在运行,这个进程就会关闭。
某个线程在【启动之前】调用Thread类的setDaemon(true)方法,就会变成后台线程,主要是用于错误log日志,还有就是软件更新/内存回收。。。
3.线程中常用的方法
// 设置线程的优先级Thread类构造方法 Constructor
Thread(); // 没有参数的构造方法
Thread(Runnable target); // 这里需要使用一个Runnable接口的实现类对象,作为当前Thread类构造方法参数,该对象,也就是Thread要执行的线程
Thread(Runnable target, String name); // Runnable接口实现类作为线程参数,然后再给线程起一个名字
成员方法 Method
void setName(String name); // 设置线程的名字
String getName(); // 获取线程的名字
/*
线程优先级
优先级取值范围: 1 - 10 1 最低, 10 最大
但是不保证优先级高的线程一定执行,也不保证优先级低的线程一定不执行。
这里优先级有且只是执行的概率大小,默认线程的优先级都是5
*/
void setPriorty(int newPriority); // 设置线程的优先级
int getPriority(); // 获取线程的优先级
static Thread currentThread(); // 返回当前方法所在线程代码块的线程对象。
static void sleep(int ms); // 当前方法在哪一个线程代码块中,哪一个线程暂停指定的毫秒数。
void yield();//线程让步,当Thread.yield();时线程就会做出让步处理,这里是直接回到就绪状态
void join();//当线程调用这个方法时,此线程就会插入到包含这段代码中的线程去,插入线程执行完毕后才会,运行被插入的线程运行。
4.线程同步
1.同步代码块
synchronized (/*锁对象*/) {
//需要同步的代码块,要上锁的代码块
}
注意:
1. 首先锁对象,必须是一个【对象】
2. 线程的锁对象是唯一的!!!同一个对象!!!,不能放在run()方法中创建这个锁对象
3. 任何对象都可以作为锁对象
4. 使用同步代码块加锁的代码,越少越好,提高效率
5. Thread.sleep(int ms) 该方法不会开启锁对象!!
2.同步方法
synchronized 返回值 方法名([参数]){}
同步方法也有自己的锁,它的锁就是调用这个方法的对象
静态同步方法没有类对象,它的锁就是这个静态同步方法所在的类对象
3.弊端:
消耗资源,效率较低,每次都要判断锁对象
4.死锁问题,不做过多解释,没什么用。
至少两个线程,两个锁对象,互相持有
5.多线程通讯
/*这里使用到两个重要的方法:
Object类的:
void wait();使当前线程进入阻塞状态,只有调用notify() 或者 notifyAll(),这个线程才会再次被调度
void notify();唤醒同步锁wait()等待的第一个线程
void notifyAll();唤醒同步锁wait()等待的所有线程
*/
class Car {
private String name;
private int pic;
private boolean falg;
public Car() {
super();
}
public Car(String name, int pic, boolean falg) {
super();
this.name = name;
this.pic = pic;
this.falg = falg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPic() {
return pic;
}
public void setPic(int pic) {
this.pic = pic;
}
public boolean isFalg() {
return falg;
}
public void setFalg(boolean falg) {
this.falg = falg;
}
@Override
public String toString() {
return "Car [name=" + name + ", pic=" + pic + ", falg=" + falg + "]";
}
}
class Factory implements Runnable{
private Car c;
int count = 0;
public Factory(Car c) {
super();
this.c = c;
}
@Override
public void run() {
synchronized(c) {
while(count < 50){
if(c.isFalg()) {
System.out.println("正在生产" + c.getName() + ":" + c.getPic());
c.notify();
count++;
c.setFalg(false);
} else {
try {
c.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
class Customer implements Runnable{
private Car c;
public Customer(Car c) {
super();
this.c = c;
}
@Override
public void run() {
synchronized (c) {
int count = 0;
while (count < 50) {
if(!c.isFalg()) {
System.out.println("消费者购买了" + c.getName());
c.notify();
count++;
c.setFalg(true);
} else {
try {
c.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
public class Demo5 {
public static void main(String[] args) {
Car c = new Car("奥迪A4l", 320000, true);
Thread t1 = new Thread(new Factory(c));
Thread t2 = new Thread(new Customer(c));
t1.start();
t2.start();
}
}