什么是线程
就是程序运行的单元, 所有的代码都是在线程中执行的
什么是进程
程序运行后, 操作系统会分配独立的内存空间, 这块空间是进程, 有自己编号。 可以通过任务管理器, 结束任务, 其本质就是释放这个进程的空间。
并发与并行
并行:单位时间片内在同时运行
并行:单位时间片内交替执行
线程实现的两种方式
方式一:1.定义一个子类继承(extends)Thread类
2.在子类中重写run方法,并将需要线程开启的代码放入run方法中
3.在测试类中创建Thread子类对象
4.使用子类对象调用start()方法
总结:该方法需要将run方法写进子类代码中,对代码侵入严重,少用。
方式二:1.定义一个实现类,实现Runnable接口
2.重写run()方法,将方法放入run方法中
3.创建Runnable实现类对象
4.创建Thread对象将Runnable实现类对象(也就是任务)放入Thread对象中
5.使用Thread对象调用start方法
注:当然可以使用匿名内部类不过方法太长不建议使用:
Thread thread = new Thread(new Runnable(){
public void run(){
}
}
实现
实现Runnable接口:
public class RedBage implements Runnable {
int count = 3;
int money = 20;
int sumMoney = count*money;
@Override
public void run() {
synchronized (this) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (sumMoney > 0) {
count--;
sumMoney = count*money;
System.out.println("恭喜" + Thread.currentThread().getName() + ",您成功抢到一个20元红包,红包还剩"+count);
} else {
System.out.println(Thread.currentThread().getName() + "抱歉,红包已经被抢完了,红包个数为:"+count);
}
}
}
}
测试类:
public class RedBageDemo {
public static void main(String[] args) {
RedBage redBage = new RedBage();
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"黄蓉","瑛姑","黄药师","周伯通","郭靖");
for (int i = 0; i < list.size(); i++) {
//Thread()中的两个参数,redBage:是必须传入的实现类对象,list.get(i)是给线程起名字不重要
//线程的名字可以使用Thread.currentThread().getName()获取,Thread.currentThread()获取当前正在运行线程对象。
Thread thread = new Thread(redBage,list.get(i));
thread.start();
}
}
}
多线程的实现结合线程池
线程池的作用:
解决频繁的创建链接和销毁链接,节约资源和时间。线程池会在池中维护几条线程的存活,当需要调用线程时从线程池中直接使用。
线程池三种创建方式:
方式一:
ExecutorService pool = Executors.newCachedThreadPool();
缺点: 没有上限, 消耗大量的内存
方式二:
ExecutorService pool = Executors.newFixedThreadPool(int count);
缺点: 虽然设定了上限, 但是没有设定闲时的线程的数量
方式三(常用):
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable