多线程快速入门
1. 线程与进程的区别
应用程序:可以执行的软件,QQ、YY、快播.
进程:正在运行的应用程序,它是线程的集合。进程中一定有一个线程,这个线程就是主线程.
线程:正在独立运行的一条执行路径.
多线程:为了提高程序的运行效率。多线程并不是提高宽带速度,而是程序效率
2. 为什么要使用多线程?
为了提高程序的运行效率
3. 多线程应用场景
多线程下载、QQ、爬虫、前端开发ajax(异步上传)、分布式job(多任务调度)、分批发送短信,使用多线程体现程序的效率
4.多线程的创建方式
1.什么是同步?什么是异步?
代码从上往下执行叫同步,又叫单线程;异步(多线程),每个线程互不影响
2.创建多线程的五种方式:
a.继承Thread类
b.实现Runnable接口
c.使用匿名内部类方式
d.callable
e.线程池创建线程
代码01 继承Thread类:/thread01/src/com/mysoft/ThreadDemo01.java
package com.mysoft;
/**
* @author lpz
* 1.继承Thread类
*/
class Thread01 extends Thread{
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println("子线程:"+i);
}
}
}
public class ThreadDemo01 {
public static void main(String[] args) {
// 1.创建一个线程
Thread t1=new Thread01();
// 2.开始执行线程 注意 开启线程不是调用run方法,而是start方法
t1.start();
//3.主线程
for(int i=0;i<30;i++) {
System.out.println("主线程:"+i);
}
}
}
代码02 使用Runnable接口方式创建线程:/thread01/src/com/mysoft/ThreadDemo02.java
package com.mysoft;
/**
*
* @author lpz
* 2.实现Runnable接口
*/
class Thread02 implements Runnable{
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println("子线程:"+i);
}
}
}
public class ThreadDemo02 {
public static void main(String[] args) {
//1.创建线程
Thread t1=new Thread(new Thread02());
//2.启动线程
t1.start();
//3.主线程
for(int i=0;i<30;i++) {
System.out.println("主线程:"+i);
}
}
}
代码03 使用匿名内部类方式创建线程:/thread01/src/com/mysoft/ThreadDemo03.java
package com.mysoft;
/**
*
* @author lpz
* 3.匿名内部类创建线程
*/
public class ThreadDemo03 {
public static void main(String[] args) {
//1.创建子线程
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println("子线程:"+i);
}
}
}).start();
//2.主线程
for(int i=0;i<30;i++) {
System.out.println("主线程:"+i);
}
}
}
5. 多线程常用api
1.常用方法
start() 获取当前线程ID
getID() 获取当前线程ID
getName() 获取当前线程名称
sleep(long mill) 休眠线程
stop() 停止线程
2.常用线程构造函数
Thread()
Thread(String name)
Thread(Runable r)
Thread(Runable r, String name)
代码04 多线程常用api:/thread01/src/com/mysoft/ThreadDemo04.java
package com.mysoft;
/**
*
* @author lpz
* 多线程常用api
*/
class Thread04 implements Runnable{
@Override
public void run() {
for(int i=0;i<30;i++) {
try {
//3.线程休眠
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//4.获取当前线程id和name
System.out.println("子线程id:"+Thread.currentThread().getId()+",子线程name:"+Thread.currentThread().getName());
}
}
}
public class ThreadDemo04 {
public static void main(String[] args) {
//1.获取主线程id和name
System.out.println("主线程id:"+Thread.currentThread().getId()+",主线程name:"+Thread.currentThread().getName());
//2.用户线程命名
Thread t1=new Thread(new Thread04(),"子线程");
t1.start();
}
}
6. 守护线程与非守护线程
守护线程:当进程不存在或主线程停止,守护线程也会被停止。
非守护线程:也叫用户线程,是指用户自定义创建的线程,主线程停止,用户线程不会停止
gc线程:是守护线程,有一个特征:和主线程一起销毁
代码05 守护线程和非守护线程:/thread01/src/com/mysoft/ThreadDemo05.java
package com.mysoft;
/**
*
* @author lpz
* 用户线程:主线程创建的线程
* 守护线程:和主线程一起销毁
*/
public class ThreadDemo05 {
public static void main(String[] args){
// 1.匿名内部类创建线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
// 4.子线程每循环一次休眠300ms
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程:" + i);
}
}
});
// 2.启动线程
t1.setDaemon(true); //true表示设置为守护线程
t1.start();
// 3.主线程
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程:" + i);
}
System.out.println("主线程运行结束......");
}
}
7. 多线程运行状态
新建状态、就绪状态、运行状态、阻塞状态、死亡状态
8. join方法作用
join作用是让其他线程变为等待, t1.join();// 让其他线程变为等待,直到当前t1线程执行完毕,才释放.在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B
代码06 join()方法的作用:/thread01/src/com/mysoft/ThreadDemo06.java
package com.mysoft;
/**
*
* @author lpz
* join()方法的作用:调用join()方法的线程执行完毕后,再执行其它线程
*/
public class ThreadDemo06 {
public static void main(String[] args) {
//1.匿名内部类创建线程
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println("子线程1:"+i);
}
}
});
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println("子线程2:"+i);
}
}
});
//2.启动子线程
t1.start();
t2.start();
//3.调用子线程t1.join()方法,等待子线程执行完毕后主线程才执行
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//4.子线程执行完毕后,执行主线程
for(int i=0;i<30;i++) {
System.out.println("主线程:"+i);
}
}
}
9. T1、T2、T3线程顺序执行
代码07 t1、t2、t3线程顺序执行:/thread01/src/com/mysoft/ThreadDemo07.java
package com.mysoft;
/**
*
* @author lpz
* T1、T2、T3线程顺序执行
*/
public class ThreadDemo07 {
static ThreadDemo07 t=new ThreadDemo07();
class T1 extends Thread{
public T1(String name) {
super(name);
}
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println(getName()+":"+i);
}
}
}
class T2 extends Thread{
public T2(String name) {
super(name);
}
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println(getName()+":"+i);
}
}
}
class T3 extends Thread{
public T3(String name) {
super(name);
}
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println(getName()+":"+i);
}
}
}
public static void main(String[] args) {
Thread t1=t.new T1("T1");
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread t2=t.new T1("T2");
t2.start();
try {
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread t3=t.new T1("T3");
t3.start();
}
}
10. 多线程模拟实现分批处理信息
需求:目前有10万个用户,现在做活动,给每一个用户发送一条祝福短信。为了提高数程序的效率,使用多线程模拟实现分批发送据。
创建项目thread_batch_send_message
1.创建实体类:/thread_batch_send_message/src/com/mysoft/bean/User.java
package com.mysoft.bean;
public class User {
private String id;
private String name;
public User() {
}
public User(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
2.创建线程类发送消息:/thread_batch_send_message/src/com/mysoft/thread/UserThread.java
package com.mysoft.thread;
import java.util.List;
import com.mysoft.bean.User;
public class UserThread extends Thread {
private List<User> list;
public UserThread(List<User> list) {
this.list = list;
}
@Override
public void run() {
for (User user : list) {
System.out.println("ThreadName:" + Thread.currentThread().getName() + ",用户编号:" + user.getId() + ",用户名字:"
+ user.getName());
}
}
}
3.初始化数据:/thread_batch_send_message/src/com/mysoft/util/InitData.java
package com.mysoft.util;
import java.util.ArrayList;
import java.util.List;
import com.mysoft.bean.User;
public class InitData {
public static List<User> initUser(int num){
List<User> list=new ArrayList<>();
for(int i=1;i<=num;i++) {
User user=new User();
user.setId("用户id"+i);
user.setName("用户名"+i);
list.add(user);
}
return list;
}
}
4.分页工具类:/thread_batch_send_message/src/com/mysoft/util/ListUtil.java
package com.mysoft.util;
import java.util.ArrayList;
import java.util.List;
public class ListUtil {
public static<T> List<List<T>> splitList(List<T> list,int pageSize){
int listSize=list.size();
int page=listSize%pageSize==0?listSize/pageSize:listSize/pageSize+1;
List<List<T>> listArray=new ArrayList<List<T>>();
for (int i = 1; i <=page ; i++) {
List<T> subList=new ArrayList<T>();
for (int j = (i-1)*pageSize; j <listSize ; j++) {
int index=(i-1)*pageSize;
if(index<=j && j<(i-1)*pageSize+pageSize) {
subList.add(list.get(j));
}
if(j==(i-1)*pageSize+pageSize) {
break;
}
}
listArray.add(subList);
}
return listArray;
}
}
5.实现发送短信:/thread_batch_send_message/src/com/mysoft/main/UserSendMessage.java
package com.mysoft.main;
import java.util.List;
import com.mysoft.bean.User;
import com.mysoft.thread.UserThread;
import com.mysoft.util.InitData;
import com.mysoft.util.ListUtil;
public class UserSendMessage {
public static void main(String[] args) throws InterruptedException {
//1.初始化数据
List<User> userList = InitData.initUser(10);
//2.定义每个线程分批发送大小
int sendNum=2;
//3.计算每个线程分批发送数据
List<List<User>> list = ListUtil.splitList(userList, sendNum);
//4.分批发送数据
for (List<User> sendList:list) {
Thread t=new UserThread(sendList);
t.start();
Thread.sleep(2000);
}
}
}