java多线程
package thread;
//继承Thread类
public class Day1 extends Thread{
// 重写run()方法
@Override
public void run() {
System.out.println("线程运行的代码");
for (int i = 0; i < 5; i++) {
System.out.println("这是逻辑代码"+i);
}
}
}
/**
* @author
* 开启run()方法后,run()方法的执行与mian()方法的执行互不相干,类似河流是俩条支流
* 控制台的结果是两个方法的总和
* 这个就是多线程的异步,是相对于start方法来说的,是并行执行没有先后顺序
*/
public class Test {
public static void main(String[] args) {
Thread day1 = new Day1();
// 启动
System.out.println("++++");
day1.start();
System.out.println("++++");
System.out.println("++++");
}
}
//实现 Runnable接口
public class Test implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程运行的代码");
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"这是逻辑代码"+i);
}
}
}
public class Test1 {
public static void main(String[] args) {
// 通过Thread创建实例
Thread thread = new Thread(new Test());
thread.start();
// 追加参数创建对象,这个可以获得线程名称,可以用来区分打印的数据是哪一个线程执行
Thread thread1 = new Thread(new Test(),"tt");
thread1.start();
}
}
并发与并行
并发:指两个或多个事件在同一时间内发生
并行:指两个或多个事件在同一时刻(同时发生)
进程
一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,一个运行的xx.exe就是一个进程。
进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位)
进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。
线程
进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。
而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
继承与实现的区别
继承:线程代码存放在Thread子类run方法中
实现:线程代码存放在接口的子类run方法
实现方法的好处
避免单继承的局限性
多个线程可以共享同一个接口实现类的对象,非常适合多个线程来处理同一份资源
使用多线程的有点
提高应用程序的响应
提高计算机系统cpu的利用率
改善程序结构
线程的生命周期
线程的同步
package thread;
/**
* 多线程调用这个方法,线程的资源共享,一个线程执行这个方法没有结束,另一个线程也开始执行了
*
* 多线程安全问题:多条语句同时操作一个线程共享数据时,会导致共享数据的错误
* 解决方法:让一个线程执行结束,再接下一个
*
* 通过synchronized同步锁来完成
* 可以直接在方法上加上这个关键字,这个锁是锁整个对象,不是某一个方法
* 普通方法加这个关键字就是不同对象就是不同锁,线程使用不同的此方法的对象,还是会出现资源共享问题
* 静态方法加这个关键字:对于所有对象都是同一个锁
*/
public class Test0 {
public static void main(String[] args) {
// 定义账户对象
Acount a = new Acount();
// 定义多线程对象
Ures ures = new Ures(a,3000);
Ures ures1 = new Ures(a,3000);
Thread t = new Thread(ures,"微信");
Thread t1 = new Thread(ures1,"支付宝");
t.start();
t1.start();
}
}
class Acount{
public static int money = 3000;
// 同步锁
// 静态同步锁 public statiac synchronized void drawing(int m) {
// public synchronized void drawing(int m) {
public void drawing(int m) {
synchronized (this){//表示当前对象的代码块被加了同步锁 synchronized (this)的代码块使用的都是同一个同步锁
// 用this锁代码块是代表当前的对象,如果在其他方法中也有
if (money < m) {
System.out.println("金额不足" + money);
} else {
System.out.println(Thread.currentThread().getName() + "账户原来金额"+money);
System.out.println(Thread.currentThread().getName() + "取款金额" + m);
money -= m;
System.out.println(Thread.currentThread().getName() + "取款后" + money);
}}
}
}
class Ures implements Runnable{
Acount acount;
int money;
public Ures( Acount acount,int money){
this.acount=acount;
this.money=money;
}
@Override
public void run() {
acount.drawing(money);
}
}

如果针对对象要加同步锁,那就加在方法上
如果针对某一段代码需要加同步锁,那就直接加在代码上
线程的死锁问题
1、不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。
2、出现死锁后,不会出现异常,不会出现提示,知识所有线程都处于阻塞状态,无法继续。
解决方法
1、专门的算法、原则
2、尽量减少同步资源的定义
3、尽量避免嵌套同步
线程通信
这三个方法只能用在有同步锁的代码块或方法上
package thread;
/**
*
*/
public class Test0 {
public static void main(String[] args) {
// 定义账户对象
Acount a = new Acount();
// 定义多线程对象
Ures ures = new Ures(a,3000);
Ures ures1 = new Ures(a,3000);
Thread t = new Thread(ures,"微信");
Thread t1 = new Thread(ures1,"支付宝");
t.start();
t1.start();
}
}
class Acount{
public static int money = 3000;
public void drawing(int m,Acount a) {
synchronized (a){
// 如果是微信操作的,先不执行,等支付宝操作,支付宝操作完,微信再执行
if ("微信".equals(Thread.currentThread().getName())) {
try {
a.wait();//当前线程进入等待阻塞状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (money < m) {
System.out.println(Thread.currentThread().getName()+"金额不足" + money);
} else {
System.out.println(Thread.currentThread().getName() + "账户原来金额"+money);
System.out.println(Thread.currentThread().getName() + "取款金额" + m);
money -= m;
System.out.println(Thread.currentThread().getName() + "取款后" + money);
}
if ("支付宝".equals(Thread.currentThread().getName())){
a.notify();//唤醒当前线程优先级最高的,进入就绪状态
// a.notifyAll();//唤醒当前所有线程,进入就绪状态
}
}
}
}
class Ures implements Runnable{
Acount acount;
int money;
public Ures( Acount acount,int money){
this.acount=acount;
this.money=money;
}
@Override
public void run() {
acount.drawing(money,acount);
}
}

浙公网安备 33010602011771号