java多线程之述解

说起线程 就不得不提进程 他们之间的关系很紧密

进程:内存中运行的应用程序 每个进程都有自己的一块内存空间 而线程是进程中的一个执行单元 一个进程中可以有多个线程 多线程的好处就是可以并发操作程序 将cpu资源利用率最大化 就像我们生活中一样 当我们在一个视屏网站下电影的时候 我们可以去做一些其他的时间 不需要一直等着电影下完再去做不会耗费多余的时间 这就是多线程的好处

如何实现多线程呢

1.继承Thread类 然后重写run方法

2.实现Runnable接口实现重写·


 

特点

继承thread类

只适用于单继承 编写简单 可以直接操作

实现runnable接口

可以实现多继承

线程的状态

1.新建状态

线程在被创建后就进入了新建状态 例如Thread thread=newThread();

2.就绪状态(也称为可执行转态)

线程再被创建后 如果调用了 start();说明该线程随时准备执行

3.运行状态

这时线程已经拿到了cpu执行权限 需要注意的是 线程可能没有被执行完 就被抢了 这时他又会回到就绪状态

4.阻塞状态

因为线程放弃了cpu的使用权 暂时停止执行操作 直到线程进入到就绪状态才有机会转到运行状态

阻塞情况分为三种:

1.等待阻塞:通过调用线程的wait方法 等待线程的执行 (例如 你去银行取钱的时候 忘记带银行卡啦 所以你打电话给你老婆让他送卡过来 在这段时间里面你就一直在等待他))

2.其他阻塞:通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态 (例如 去银行取钱的时候感觉有点困 睡着了 别人也进不来)

3.同步阻塞:

线程在获取 synchronized同步锁失败(因为锁被其他线程锁占用)他会进入到同步阻塞状态 也称只为死锁() (例如 你去银行取钱一直在排队等 但是别人在银行atm里面就一直不出来 但是你不死心 还是一直在等)

5.死亡状态

线程执行完退出exit或者因异常退出

线程调度

join() 插队 让当前线程执行完了之后在执行其他线程

join( long millis); 让出时间让你先执行 时间到了以后再继续抢

yield(); 暂停这次执行机会 再来竞争(相当于让你一次)

sleep() 让此线程休眠多长时间

notify()   唤醒在此对象监视器上等待的单个线程。

notifyAll()  唤醒在此对象监视器上等待的所有线程。

wait()    让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)。

java线程安全

当多个线程去操作同一对象的同一个属性时,执行的结果可能与预期不符。这时 这个对象就称为线程不安全的对象  这个对象所在的类成为线程不安全类

这时我们有两种方法可以解决

1.同步方法

只需要在方法上添加一个synchronized修饰符即可

这种方法非常简单 但是效率很低 因为他把所有的操作都上锁了(例如去银行取钱应该是一个完整的操作 我们只需要将取卡 插卡 取钱 拿卡这几部上锁就够了 因为我们取钱的时候卡已经拿出来了放在手上 如果等到我了 我直接就可以去插卡了 很快 但是如果我取卡的步骤放到atm机里面去 找了很半天才找到卡是不是很浪费时间 如果每个人都是这样时间更长 所以说我在外面将卡找好了就可以节省时间)

2.同步代码块

需要将那些一起执行的代玛写在代码块中

synchronized(这里是一个锁对象 这个锁对象必须是一个不会改变的对象){

这里写的是那些需要一起执行的代码块

}

接下来举例说明

去银行取钱如果使用单线程会发生什么?

 1 package com.newroad.thread.test;
 2 //账户类
 3 public class Account {
 4     private double balance;
 5     private Object lock=new Object();
 6     public Account(double balance) {
 7         super();
 8         this.balance = balance;
 9     }
10     public  void withdrawMoney(double money) {
11     String name=Thread.currentThread().getName();
12     System.out.println(name+"取款前账户余额为:"+balance);
13         if (balance>=money) {
14             balance=balance-money;
15             System.out.println(name+"取款金额为:"+money +"取款后,余额为:"+balance);
16         }else {
17             System.out.println(name+"余额不足,账户余额为:"+balance+"取款金额为;"+money);
18         }
19
20     }
21
3
34
35 }
36
37 //线程类
38 package com.newroad.thread.test;
40 public class PersonThread extends Thread {
41     private Account account;
42     private double drawbalance;
43     public PersonThread(Account account, double drawbalance) {
44         super();
45         this.account = account;
46         this.drawbalance = drawbalance;
47     }
48
49     @Override
50     public void run() {
51         account.withdrawMoney(drawbalance);
52
53     }
54
55 }
56
57
58 //这是测试类
59 package com.newroad.thread.test;
60
61 public class Test {
62 public static void main(String[] args) {
63     Account account=new Account(4000);
64     PersonThread p=new PersonThread(account, 2400);
65     PersonThread p1=new PersonThread(account, 1000);
66     PersonThread p2=new PersonThread(account, 600);
67     p.setName("张三");
68     p1.setName("张三媳妇");
69     p2.setName("张三爸");
70     p.start();
71     p1.start();
72     p2.start();
73  }
74 }

这是运行后的结果 明显不对 我们可以明显发现 只有张三的操作是没有问题的 他媳妇和他爸都是有问题的 这肯定是有问题的 这时就可以使用加锁的方法 让一个线程执行完了在让其他线程在执行 而生活中 我们去银行ATM机上取钱都会有一个门 等我所有操作都完了其他人才能进来 这就相当于我们程序中的锁

这时我们只需要修改 账户类就可以啦

 1 package com.newroad.thread.test;
 2
 3 public class Account {
 4     private double balance;
 5     private Object lock = new Object();
 6
 7     public Account(double balance) {
 8         super();
 9         this.balance = balance;
10     }
11     public void withdrawMoney(double money) {
12         String name = Thread.currentThread().getName();
13         synchronized (this) {
14             System.out.println(name + "取款前账户余额为:" + balance);
15             if (this.balance >= money) {
16                 balance = balance - money;
17                 System.out.println(name + "取款金额为:" + money + "取款后,余额为:" + balance);
18             } else {
19                 System.out.println(name + "余额不足,账户余额为:" + balance + "取款金额为;" + money);
20             }
21         }
22     }
23
24 }

这时我们就可以发现就没问题了

原文地址:https://www.cnblogs.com/hengly/p/10664392.html

时间: 2024-11-03 18:17:49

java多线程之述解的相关文章

Java多线程编程详解

线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问. 由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synch

40个Java多线程问题详解复习

1.多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡.所谓"知其然知其所以然","会用"只是"知其然","为什么用"才是"知其所以然",只有达到"知其然知其所以然"的程度才可以说是把一个知识点运用自如.OK,下面说说我对这个问题的看法: (1)发挥多核CPU的优势 随着工业的进步,现在的笔记本.台式机乃至商用的应用服务器

java 多线程上传解压文件

举个公司项目开发遇到的一个简单例子,用户上传压缩文件到服务器后,要对该压缩包进行两个操作,一是将该压缩包复制到指定目录,一是将该压缩包解压到另一指定目录,最终响应用户提示文件上传成功.如果压缩包很大的话,上传后进行的复制和解压功能也会占用很长时间,用户就会等待很长的时间.其实复制和解压的功能和用户操作没有直接关系,完全可以独立出来,其解决的思路如下: 当用户上传压缩文件完毕之后,我们立即创建两个线程,一是复制压缩文件的线程:二是解压压缩文件的线程.我们可以通过线程的构造方法把文件的信息传递给相应

JAVA多线程synchronized详解

Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行.另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块. 然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块. 尤其关键

Java多线程详解(二)

评论区留下邮箱可获得<Java多线程设计模式详解> 转载请指明来源 1)后台线程 后台线程是为其他线程服务的一种线程,像JVM的垃圾回收线程就是一种后台线程.后台线程总是等到非后台线程死亡之后,后台线程没有了服务对象,不久就会自动死亡,不再复活.利用setDaemon方法可以把一个线程设置为后台线程,但必须在线程启动之前调用. 例如 : /* * @author [email protected] */ public class DaemonThread extends Thread { pu

java多线程详解

转自:线程间通信.等待唤醒机制.生产者消费者问题(Lock,Condition).停止线程和守护线程.线程优先级 1  线程间通信 1.1  线程间通信 其实就是多个线程在操作同一个资源,但是操作的动作不同. 比如一个线程给一个变量赋值,而另一个线程打印这个变量. 1.2  等待唤醒机制 wait():将线程等待,释放了CPU执行权,同时将线程对象存储到线程池中. notify():唤醒线程池中一个等待的线程,若线程池有多个等待的线程,则任意唤醒一个. notifyAll():唤醒线程池中,所有

Java 多线程详解(二)------如何创建进程和线程

Java 多线程详解(一)------概念的引入:http://www.cnblogs.com/ysocean/p/6882988.html 在上一篇博客中,我们已经介绍了并发和并行的区别,以及进程和线程的理解,那么在Java 中如何创建进程和线程呢? 1.在 Windows 操作系统中创建进程 在 windows 操作系统中,我们创建一个进程通常就是打开某个应用软件,这便在电脑中创建了一个进程.更原始一点的,我们在命令提示符中来做(我们以打开记事本这个进程为例): 第一步:windows+R,

Java 多线程详解(五)------线程的声明周期

Java 多线程详解(一)------概念的引入:http://www.cnblogs.com/ysocean/p/6882988.html Java 多线程详解(二)------如何创建进程和线程:http://www.cnblogs.com/ysocean/p/6883491.html Java 多线程详解(三)------线程的同步:http://www.cnblogs.com/ysocean/p/6883729.html Java 多线程详解(四)------生产者和消费者:http:/

java 多线程详解

线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问. 由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synch