多线程:多个程序并行运行而非串行运行
线程运行状态图:
一、实现线程的手段:
1.继承Thread类:
public class Runner extends Thread{
private String name;
public Runner(String name) {
this.name = name;
}
//线程运行期间会执行的东西
public void run() {
for (int i = 1;i <= 100;i++) {
System.out.println(name+"运行了"+i+"次");
}
}
public static void main(String[] args) throws InterruptedException {
Runner r = new Runner("线程1");
//进入就绪状态
r.start();
Runner r1 = new Runner("线程2");
//进入就绪状态
r1.start();
}
}
2.实现Runnable接口:
public class MyRunner implements Runnable{
private String name;
public MyRunner(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 1;i <= 100;i++) {
System.out.println(name+"运行了"+i+"次");
}
}
public static void main(String[] args) {
MyRunner mr = new MyRunner("线程1");
Thread t1 = new Thread(mr);
t1.start();
MyRunner mr1 = new MyRunner("线程2");
Thread t2 = new Thread(mr1);
t2.start();
}
}
二、匿名类和Lambda表达式:
1.匿名类:
One one = new One(){
//创建了一个实现了One接口的一个类,并且创建了它的对象
@Override
public void test() {
System.out.println("我是匿名类实现的test方法");
}
};
One one1 = new One(){
public void test() {
System.out.println("我是匿名类实现的test方法1");
}
};
one.test();
one1.test();
2.匿名类实现线程:
new Thread(new Runnable() {
public void run() {
for (int i = 1;i <= 100;i++){
System.out.println("线程1运行了:"+i+"次");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 1;i <= 100;i++){
System.out.println("线程2运行了:"+i+"次");
}
}
}).start();
3.Lambda表达式:
One one = () ->{
System.out.println("我是Lambda表达式的实现");
};
one.test();
注意:Lambda表达式只能针对单一方法接口进行实现
4.lambda表达式对于线程的实现 :
//Lambda表达式实现线程使用
new Thread(()->{
for (int i = 1;i <= 100;i++){
System.out.println(i);
}
}).start();
new Thread(()->{
for (int i = 1;i <= 100;i++){
System.out.println(i);
}
}).start();
三、线程锁:
1.意义:
线程锁是将线程由并行改为串行的一种技术手段
2线程案例:
生产消费者模型
生产者 : 负责生产产品存储在仓库中
消费者 : 负责购买仓库中已存在的商品
仓库 : 负责存储商品
注意 : 在生产消费者模型中,生产者和消费者必须使用同一个仓库进行处理
3.如何解决生产消费者模型中非线程安全的数据访问的问题?
使用synchronized互斥锁关键字进行处理
synchronized : 让本来处于并行的线程变为串行效果执行,锁的执行效果是固定的,但是具体应用要考虑具体业务场景进行分配.
4. synchronized的语法:
a.synchronized可以写在方法上,表示访问该方法的线程会拿到一把锁
b.synchronized也可以使用锁块来声明使用谁的锁
四.线程中常用方法:
1.sleep方法:让程序进入休眠等待状态,等待中并不会释放掉锁
2.yield方法:释放使用权,但不会释放锁
3.wait方法:让当前线程进入等待状态,但是它会释放的掉锁
4.notify和notifyAll : 一个是随机唤醒单个线程,一个是唤醒全部线程
5.join方法:强制某个线程进入CPU调度并且执行完毕
sleep和wait的区别:
(1).调用方式上的差异 sleep用Thread.sleep,wait使用对象调用,而且对象必须是当前线程所获取的对象锁的对象.
(2).sleep中不会释放锁,而wait会释放锁
(3).调用的机制不同
六 、死锁:
死锁是一种线程使用过程中会出现的问题,我们要考虑如何避免和解决
(1).增加资源,避免资源争抢
(2).合理的设置有资源争抢的线程之间的启动顺序
本人会定期发表关于Java的相关知识,如果有错误请指出,觉得好请点赞,收藏加关注,谢谢!!