进程:进行资源分配和调度的一个独立单位。
进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
主要能体现到多线程提高程序效率。
举例: 迅雷多线程下载、分批发送短信等。
1 /** 2 * 3 * @classDesc: 功能描述:(创建多线程例子-Thread类 重写run方法) 4 * @author: 余胜军 5 * @version: v1.0 6 * @copyright:上海每特教育科技有限公司 7 */ 8 class CreateThread extends Thread { 9 // run方法中编写 多线程需要执行的代码 10 publicvoid run() { 11 for (inti = 0; i< 10; i++) { 12 System.out.println("i:" + i); 13 } 14 } 15 } 16 publicclass ThreadDemo { 17 18 publicstaticvoid main(String[] args) { 19 System.out.println("-----多线程创建开始-----"); 20 // 1.创建一个线程 21 CreateThread createThread = new CreateThread(); 22 // 2.开始执行线程 注意 开启线程不是调用run方法,而是start方法 23 System.out.println("-----多线程创建启动-----"); 24 createThread.start(); 25 System.out.println("-----多线程创建结束-----"); 26 } 27 28 }
调用start方法后,代码并没有从上往下执行,而是有一条新的执行分之。注意:画图演示多线程不同执行路径。
1 /** 2 * 3 * @classDesc: 功能描述:(创建多线程例子-Thread类 重写run方法) 4 * @author: 余胜军 5 * @version: v1.0 6 * @copyright:上海每特教育科技有限公司 7 */ 8 class CreateRunnable implements Runnable { 9 10 @Override 11 publicvoid run() { 12 for (inti = 0; i< 10; i++) { 13 System.out.println("i:" + i); 14 } 15 } 16 17 } 18 19 /** 20 * 21 * @classDesc: 功能描述:(实现Runnable接口,重写run方法) 22 * @author: 余胜军 23 * @version: v1.0 24 * @copyright:上海每特教育科技有限公司 25 */ 26 publicclass ThreadDemo2 { 27 publicstaticvoid main(String[] args) { 28 System.out.println("-----多线程创建开始-----"); 29 // 1.创建一个线程 30 CreateRunnable createThread = new CreateRunnable(); 31 // 2.开始执行线程 注意 开启线程不是调用run方法,而是start方法 32 System.out.println("-----多线程创建启动-----"); 33 Thread thread = new Thread(createThread); 34 thread.start(); 35 System.out.println("-----多线程创建结束-----"); 36 } 37 }
1 System.out.println("-----多线程创建开始-----"); 2 Thread thread = new Thread(new Runnable() { 3 public void run() { 4 for (int i = 0; i< 10; i++) { 5 System.out.println("i:" + i); 6 } 7 } 8 }); 9 thread.start(); 10 System.out.println("-----多线程创建结束-----");
使用实现实现Runnable接口好,原因实现了接口还可以继续继承,继承了类不能再继承。
开始执行线程 注意 开启线程不是调用run方法,而是start方法
调用run知识使用实例调用方法。
Java中有两种线程,一种是用户线程,另一种是守护线程。
用户线程是指用户自定义创建的线程,主线程停止,用户线程不会停止
守护线程当进程不存在或主线程停止,守护线程也会被停止。
使用setDaemon(true)方法设置为守护线程。
当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码
一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。
处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。
当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.
线程运行过程中,可能由于各种原因进入阻塞状态:
1>线程通过调用sleep方法进入睡眠状态;
2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
3>线程试图得到一个锁,而该锁正被其他线程持有;
4>线程在等待某个触发条件;
有两个原因会导致线程死亡:
1) run方法正常退出而自然死亡,
2) 一个未捕获的异常终止了run方法而使线程猝死。
为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.
1 class JoinThread implements Runnable { 2 3 public void run() { 4 for (int i = 0; i < 100; i++) { 5 System.out.println(Thread.currentThread().getName() + "---i:" + i); 6 } 7 } 8 } 9 18 public class JoinThreadDemo { 19 20 public static void main(String[] args) { 21 JoinThread joinThread = new JoinThread(); 22 Thread t1 = new Thread(joinThread); 23 Thread t2 = new Thread(joinThread); 24 t1.start(); 25 t2.start(); 26 try { 27 //其他线程变为等待状态,等t1线程执行完成之后才能执行join方法。 28 t1.join(); 29 } catch (Exception e) { 30 31 } 32 for (int i = 0; i < 100; i++) { 33 System.out.println("main ---i:" + i); 34 } 35 } 36 37 }
Thread.yield()方法的作用:暂停当前正在执行的线程,并执行其他线程。(可能没有效果)
yield()让当前正在运行的线程回到可运行状态,以允许具有相同优先级的其他线程获得运行的机会。因此,使用yield()的目的是让具有相同优先级的线程之间能够适当的轮换执行。但是,实际中无法保证yield()达到让步的目的,因为,让步的线程可能被线程调度程序再次选中。
结论:大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。
join作用是让其他线程变为等待, t1.join();// 让其他线程变为等待,直到当前t1线程执行完毕,才释放。
thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
需求:目前蚂蚁课堂有10万个用户,现在蚂蚁课堂需要做活动,给每一个用户发送一条祝福短信。
为了提高数程序的效率,请使用多线程技术分批发送据。
每开一个线程,都会占用CPU资源
服务器(电脑)配置 CPU 核数
1 package com.itmayiedu.enity; 2 /** 3 * 4 */ 5 publicclass UserEntity { 6 private String userId; 7 private String userName; 8 public String getUserId() { 9 returnuserId; 10 } 11 publicvoid setUserId(String userId) { 12 this.userId = userId; 13 } 14 public String getUserName() { 15 return userName; 16 } 17 18 publicvoid setUserName(String userName) { 19 this.userName = userName; 20 } 21 }
1 Class UserThreadextends Thread { 2 private List<UserEntity>list; 3 /** 4 * 通过构造函数 传入每个线程需要执行的发送短信内容 5 * 6 * @param list 7 */ 8 public UserThread(List<UserEntity>list) { 9 this.list = list; 10 } 11 /** 12 * 13 */ 14 publicvoid run() { 15 for (UserEntity userEntity : list) { 16 System.out.println("threadName:" + Thread.currentThread().getName() + "-学员编号:" + userEntity.getUserId() 17 + "---学员名称:" + userEntity.getUserName()); 18 // 调用发送短信具体代码 19 } 20 } 21 }
1 publicstatic List<UserEntity> init() { 2 List<UserEntity>list = new ArrayList<UserEntity>(); 3 for (inti = 1; i<= 140; i++) { 4 UserEntity userEntity = new UserEntity(); 5 userEntity.setUserId("userId" + i); 6 userEntity.setUserName("userName" + i); 7 list.add(userEntity); 8 } 9 returnlist; 10 11 }
public class ListUtils { /** * */ static public<T> List<List<T>> splitList(List<T> list, int pageSize) { int listSize = list.size(); int page = (listSize + (pageSize - 1)) / pageSize; List<List<T>>listArray = new ArrayList<List<T>>(); for (int i = 0; i<page; i++) { List<T>subList = new ArrayList<T>(); for (int j = 0; j<listSize; j++) { int pageIndex = ((j + 1) + (pageSize - 1)) / pageSize; if (pageIndex == (i + 1)) { subList.add(list.get(j)); } if ((j + 1) == ((j + 1) * pageSize)) { break; } } listArray.add(subList); } return listArray; } }
1 Public staticvoid main(String[] args) { 2 // 1.初始化用户数据 3 List<UserEntity>listUserEntity = init(); 4 // 2.计算创建创建多少个线程并且每一个线程需要执行“分批发送短信用户” 5 // 每一个线程分批跑多少 6 intuserThreadPage = 50; 7 // 计算所有线程数 8 List<List<UserEntity>>splitUserList = ListUtils.splitList(listUserEntity, userThreadPage); 9 intthreadSaze = splitUserList.size(); 10 for (inti = 0; i<threadSaze; i++) { 11 List<UserEntity>list = splitUserList.get(i); 12 UserThread userThread = new UserThread(list); 13 // 3.执行任务发送短信 14 userThread.start(); 15 } 16 17 }
----总结来自蚂蚁课堂&每特学院材料
原文:https://www.cnblogs.com/dingpeng9055/p/10513577.html