系统中,为了更换的利用CPU资源,提高运行效率,就一定会用到多线程;那么JAVA中的多线程又是什么样的? 接下来就一一测试JAVA中线程的使用方法:
1, 线程的基本用法:
package thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
*@description
*
* JAVA 线程的用法测试
*
*@date 2018/1/3
*@author geYang
**/
public class MyThread {
/**
* 知识点:
*
* A:什么是进程,什么是线程?
* 1, 进程 : 进程是正在运行的程序,是线程的集合,每一个应用程序中都会有一个进程, 是执行某个程序, 一个操作系统中会有多个进程;
* 2, 线程 : 线程是CPU的最小执行单元,一条执行路径,一个执行流程,在任何一个进程中都会有一个线程,称为该进程的主线程;
* 如 main方法就是该程序的主线程; 每个线程间是独立,互不影响,交替进行的;
*
* 为什么使用多线程:
* 使用多线程,更好的利用CPU的资源,提高程序运行效率,提高用户体验; 多线程并不是提高宽带速度,而只是提高程序效率;
*
* B:创建线程有那些方式:
* 1: 使用继承 Thread 类,重写 run() 的方式;
* 2: 使用实现Runnable接口方式;
* 3: 使用匿名内部类方式;
* 4: 使用Calable和Future创建具备返回值的线程;
* 5: 使用线程池创建线程;
*
* C:创建线程的那种方法好?
* 实现接口的方法,面向接口编程;
*
* D:同步 和 异步:
* 1: 同步: 代码从上往下顺序的执行;单线程;
* 2: 异步: 多线程; 多个执行路径,互不影响; CPU执行权,每次CPU调度不相同;
*
* E:什么是守护线程,什么是非守护线程:
* 1: 守护线程: 守护线程和主线程一起销毁; 如我们的gc线程(垃圾回收),它有一个特征:主线程挂掉,守护线程也会挂掉;
* 2: 非守护线程: 和主线程互不影响; 如用户线程,用户创建的线程,当主线程挂掉之后,用户线程还会继续执行;
*
* F:并行与并发:
* 1: 并行:多个CPU实例或者多台机器同时执行一段处理逻辑,是真正的同时;
* 2: 并发:通过CPU调度算法,让用户看上去同时执行,实际上从CPU操作层面不是真正的同时;
*
* G:线程的几种状态:
* 新建(new Thred())------->准备状态(start())----------->运行状态(run())----->死亡(stop())
* ^ /
* \---休眠状态(sleep(),wait())<---
* */
/**
* main 方法 为当前项目的主线程
* @throws Exception
* */
public static void main(String[] args) throws Exception {
/* JAVA开启线程的几种方法 */
//1: 调用继承Thread的线程创建方法:
new ThreadOne().start();
//2: 使用实现Runnable接口方式;
new Thread(new ThreadTwo()).start();
//3: 使用匿名内部类创建
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println("run3::"+i);
}
}
}).start();
new Thread(()->System.out.println("run3.1::In Java8")).start();
//4: 使用Calable和Future创建具备返回值的线程:
ThreadFour t4 = new ThreadFour();
// 使用FutureTask来包装Callable对象
FutureTask<Object> task = new FutureTask<Object>(t4);
new Thread(task).start();
try {
System.out.println("run后返回值"+task.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
/**
* 5: 使用线程池创建线程
* java.uitl.concurrent.ThreadPoolExecutor
* 类是线程池中最核心的一个类,因此如果要透彻地了解Java中的线程池,必须先了解这个类;
* 线程池部分内容较多,一会在新的文件中测试;
*
* */
// 主线程循环
for(int i=0;i<5;i++){
System.out.println("main::"+i);
}
/**
* 线程常用API:
* */
/* 获取线程的ID和名称 */
Thread threadMain = Thread.currentThread();
long id = threadMain.getId();
String name = threadMain.getName();
System.out.println("主线程ID="+id+"主线程名="+name);
ThreadOne threadOne = new ThreadOne();
System.out.println("threadOne-ID="+threadOne.getId()+"子线程名="+threadOne.getName());
Thread threadTwo = new Thread(new ThreadTwo(),"xx");
System.out.println("threadTwo-ID="+threadTwo.getId()+"子线程名="+threadTwo.getName());
/* 设置线程名称 */
threadTwo.setName("ThreadTwo");
System.out.println("threadTwo-ID="+threadTwo.getId()+"子线程名="+threadTwo.getName());
/* 休眠 */
// 主线程休眠;
Thread.sleep(1000);
/* 设置线程为守护线程 */
threadTwo.setDaemon(true);
threadTwo.start();
/* 优先级 */
threadTwo.join();
for(int i=0; i<5 ; i++){
System.out.println("Hello world");
}
}
}
/**
* 1: 继承Thread重写run方法创建
* */
class ThreadOne extends Thread{
@Override
public void run() {
System.out.println("run1_ID="+getId()+"name="+getName());
for(int i=0;i<5;i++){
try {
//设置线程休眠时间:单位毫秒
sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("ID:"+getId()+"run1::"+i);
//立马停止线程,不安全,不建议使用
//stop();
}
}
}
/**
* 2: 实现Runnable接口创建线程
**/
class ThreadTwo implements Runnable{
public ThreadTwo(){}
public ThreadTwo(Thread thread){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"--run2::"+i);
}
}
}
/**
* 3: 实现Callable接口来实现线程
* */
class ThreadFour implements Callable<Object>{
@Override
public Object call() throws Exception {
for(int i=0;i<5;i++){
System.out.println("run4::"+i);
}
return 5;
}
}
2: 测试线程优先级:
package thread;
/**
* 测试t1,t2,t3 顺序执行(优先级)
*
* join()
*
*
**/
public class MyTherdTest1 {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<5;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1:::"+i);
}
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for(int i=0;i<5;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2:::"+i);
}
}
}, "t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for(int i=0;i<5;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3:::"+i);
}
}
}, "t3");
Thread t4 = new Thread(new Thread4(t3),"t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Thread4 implements Runnable{
private Thread thread;
public Thread4(){}
public Thread4(Thread thread){
this.thread = thread;
}
@Override
public void run() {
if(this.thread!=null){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0;i<5;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":::"+i);
}
}
}
3: 简单分配处理事件 测试:
package thread;
import java.util.ArrayList;
import java.util.List;
/**
* 多线程 分批处理 事件 测试;
*
* 分批发送短信举例;
*
* */
public class MyTherdTest2 {
public static void main(String[] args) {
//1, 初始化用户数据;
List<User> listUser = listUser(10);
//2, 定义每批大小;
int size = 2;
//3, 分隔数据;
List<List<User>> page = new PageUtil<User>(size, listUser).page();
//4, 发送
for(List<User> list : page){
new Thread(new Send<User>(list)).start();
}
}
private static List<User> listUser(int size){
List<User> list = new ArrayList<>();
for(int i=0;i<size;i++){
list.add(new User(i,i+""+i));
}
return list;
}
}
/**
* 发送工具
* */
class Send<T> implements Runnable{
private List<T> list;
public Send(List<T> list) {
this.list = list;
}
@Override
public void run() {
for(T t : list){
System.out.println(Thread.currentThread().getName()+";::"+t);
}
}
}
/**
* 分页工具
* */
class PageUtil<T>{
private int size;
private List<T> list;
public PageUtil(int size, List<T> list) {
this.size = size;
this.list = list;
}
public List<List<T>> page(){
int pages = (list.size()+size-1)/size;
// System.out.println("页数:"+pages);
// System.out.println("大小:"+size);
List<List<T>> listL = new ArrayList<>();
for(int i=0; i < pages; i++){
int start = i*size;
List<T> listT = new ArrayList<>();
for(int j=start; j<start+size && j<list.size(); j++){
// System.out.println(list.get(j));
listT.add(list.get(j));
}
// System.out.println(listT);
// System.out.println("==========");
listL.add(listT);
}
return listL;
}
}
/**
* 用户对象
* */
class User {
private int id;
private String phone;
public User() {
}
public User(int id, String phone) {
this.id = id;
this.phone = phone;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "User [id=" + id + ", phone=" + phone + "]";
}
}
好了,线程的简单使用就这样了,下次再来看看关于线程更高级的用法; 欢迎讨论交流;