Java高级编程 多线程
文章目录
一、进程与线程
一个程序有一个进程
一个进程包含多个线程(必须有一个主线程)
并发:
在同一时刻,有多个指令在单个CPU上交替执行
并行:
在同一时刻,有多个指令在多个CPU上同时执行
查看线程
java
Thread t = Thread.currentThread();//获得当前线程
二、线程创建方式
1.继承Thread类,重写run方法,调用start方法
2.实现Runnable接口,重写run方法,创建Thread对象new Thread(Runnable),调用start
3.实现Callable<数据类型>,重写call方法 **注意:**Callable有返回值
java
package com.hz.ch01;
public class MyThread extends Thread{
public void run() {
//书写线程要执行的代码
for(int i = 0; i<100; i++) {
System.out.println(getName()+"whfoawh");
}
}
}
package com.hz.ch01;
public class Text {
public static void main(String[] args) {
/*
* 多线程的第一种启动方式:
* 1.自己定义一个类继承Thread
* 2.重写run方法
* 3.创建子类的对象,并启动线程
*/
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
//开启线程
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
}
}
java
package com.hz.ch02;
public class MyRun implements Runnable{
@Override
public void run() {
//书写线程要执行的代码
for(int i = 0;i < 100;i++) {
//获取当前线程对象
Thread t = Thread.currentThread();
System.out.println(t.getName()+"HelloWorld");
}
}
}
package com.hz.ch02;
public class Text01 {
public static void main(String[] args) {
/*
* 多线程的第二种启动方式:
* 1.自己定义一个类实现Runnable接口
* 2.重写里面的run方法
* 3.创建自己的类的对象
* 4.创建一个Thread类的对象,并开启线程
*
*/
//创建MyRun的对象
//表示多线程要执行的任务
MyRun mr = new MyRun();
//创建线程对象
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);
//给线程设置名字
t1.setName("线程1");
t2.setName("线程2");
//开启线程
t1.start();
t2.start();
}
}
java
package com.hz.ch03;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
//求1-100之间的和
int sum = 0;
for(int i = 1;i<=100;i++) {
sum = sum+i;
}
return sum;
}
}
package com.hz.ch03;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Text01 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
/*
* 多线程的第三种运行结果
* 特点:可以获取到多线程运行的结果
*
* 1,创建一个类MyCallable实现Callable接口
* 2.重写call(是有返回值的,表示多线程运行的结果)
* 3.创建MyCallable的对象(表示多线程要执行的任物)
* 4.创建FutureTask的对象(作用管理多线程运行的结果)
* 5.创建Three类的对象,并启动(表示线程)
*
*
*/
//创建MyCallable的对象(表示多线程要执行的任物)
MyCallable mc = new MyCallable();
//创建FutureTask的对象(作用管理多线程运行的结果)
FutureTask<Integer> ft = new FutureTask<>(mc);
//创建线程的对象
Thread t1 = new Thread(ft);
//启动线程
t1.start();
//获取多线程运行的结果
Integer resule = ft.get();
System.out.println(resule);
}
}
三、线程状态
创建状态:new Thread
就绪状态:调用start()方法
运行状态:执行run()方法
阻塞状态:调用sleep,join会进入阻塞状态,恢复后改为就绪状态->运行
死亡状态:run()运行结束
四、线程常用方法
方 法 | 说 明 |
---|---|
void setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程 |
boolean isAlive() | 测试线程是否处于活动状态 |
wait() 暂停一个线程
notilfy 唤起一个线程
注意:join写在哪个线程阻塞谁,谁调用谁强制执行
sleep使用毫秒 1000毫秒=1秒
使用synchronized修饰的方法控制对类成员变量的访问
访问修饰符 synchronized 返回类型 方法名(参数列表){......}
synchronized 访问修饰符 返回类型 方法名(参数列表){......}
synchronized就是为当前的线程声明一把锁
java
/**
* 多人抢票线程
* @author 26255
*
*/
public class Writ1 implements Runnable{
public Integer votes = 10;
public Integer num = 0;
@Override
public void run() {
while(true) {
synchronized (this) {
if(votes<=0) {
break;
}
votes--;
num++;
System.out.println(Thread.currentThread().getName()+"抢到了第几"+num+"张票,剩余"+votes+"张票");
}
//模拟网络延时
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
-------------------------------------------------------------------------------
public static void main(String[] args) {
Writ1 writ = new Writ1();
Thread b1 = new Thread(writ,"票口一");
Thread b2 = new Thread(writ,"票口二");
Thread b3 = new Thread(writ,"票口三");
b1.start();
b2.start();
b3.start();
}
五、线程安全
线程安全的类型
** ** | 方法是否同步 | 效率比较 | 适合场景 |
---|---|---|---|
线程安全 | 是 | 低 | 多线程并发共享资源 |
非线程安全 | 否 | 高 | 单线程 |
为达到安全性和效率的平衡,可以根据实际场景来选择合适的类型
线程安全的类型
查看ArrayList类的add()方法定义
ArrayList类的add()方法为非同步方法
当多个线程向同一个ArrayList对象添加数据时,可能出现数据不一致问题
ArrayList为非线程安全的类型
Hashtable &&HashMap
Hashtable
继承关系
实现了Map接口,Hashtable继承Dictionary类
线程安全,效率较低
键和值都不允许为null
HashMap
继承关系实现了Map接口,继承AbstractMap类
非线程安全,效率较高
键和值都允许为null
StringBuffer && StringBuilder
前者线程安全,后者非线程安全
当多个线程向同一个ArrayList对象添加数据时,可能出现数据不一致问题
ArrayList为非线程安全的类型
Hashtable &&HashMap
Hashtable
继承关系
实现了Map接口,Hashtable继承Dictionary类
线程安全,效率较低
键和值都不允许为null
HashMap
继承关系实现了Map接口,继承AbstractMap类
非线程安全,效率较高
键和值都允许为null
StringBuffer && StringBuilder
前者线程安全,后者非线程安全