编程开发之--java多线程学习总结(1)问题引入与概念叙述
1、经典问题,火车站售票,公共票源箱,多个窗口同时取箱中车票销售
package com.lfy.ThreadsSynchronize; /**
* 解决办法分析:即我们不能同时让超过两个以上的线程进入到 if(num>0)的代码块中
* 1、使用 同步代码块 2、使用 同步方法 3、使用 锁机制
*/
public class TicketSell1 extends Thread{ //定义一共有 50 张票,注意声明为 static,表示几个窗口共享
private static int num = 50; //调用父类构造方法,给线程命名
public TicketSell1(String string) {
super(string);
} @Override
public void run() {
//票分 50 次卖完
for(int i = 0 ; i < 50 ;i ++){
if(num > 0){
try {
Thread.sleep(10);//模拟卖票需要一定的时间
} catch (InterruptedException e) {
// 由于父类的 run()方法没有抛出任何异常,根据继承的原则,子类抛出的异常不能大于父类, 故我们这里也不能抛出异常
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+(--num)+"张");
}
}
}
}
2、对于解决办法,java中专门提供了synchronized关键字处理多线程同步问题,有了synchronized关键字,多线程程序的运行结果将变得可以控制。synchronized关键字用于保护共享数据。synchronized实现同步的机制:synchronized依靠"锁"机制进行多线程同步,"锁"有2种,一种是对象锁,一种是类锁。synchronized关键字修饰普通方法时,获得的锁是对象锁,也就是this。而修饰静态方法时,锁是类锁,也就是类名.class。
阻塞:A、B线程同时运行,由于锁的控制,某时刻A线程还能继续执行,B线程被挂起等待了,就说B线程被阻塞了。
(1)对象锁,使用synchronized修饰多个普通方法,当不同线程调用同一个对象的不同被synchronized修饰过的方法时,第一个调用被synchronized修饰过的方法的线程会得到对象锁,其他线程处于阻塞状态,直至第一个得到锁的线程退出被synchronized修饰过的方法。举个例子:
package lfy;
public class TestSynchronized {
public synchronized void method1() throws InterruptedException {
System.out.println("method1 begin at:" + System.currentTimeMillis());
System.out.println("method1 begin to sleep 5s");
Thread.sleep(5000);
System.out.println("method1 end at:" + System.currentTimeMillis());
}
public synchronized void method2() throws InterruptedException {
for(int i=0;i<5;i++) {
System.out.println("method2 running");
Thread.sleep(200);
}
}
static TestSynchronized instance = new TestSynchronized();
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
instance.method1();
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=1; i<4; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread1 still alive");
}
System.out.println("Thread1 over");
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
instance.method2();
System.out.println("Thread2 over");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
thread2.start();
}
}
运行结果:

解释:创建了一个对象实例instance,创建两个线程Thread1、Thread2,它们分别调用instance的mothod1、mothod2方法,由于线程1先启动并先访问到被synchronized修饰的mothod1,此时instance对mothod2上锁,线程2此时只能等待mothod2的锁被释放,才能执行mothod2方法。这就是对象锁机制。
(2)类锁,对所有对象调用被synchronized修饰的static方法进行锁定,没有被synchronized修饰的static方法不会被上锁。
package lfy;
public class TestSynchronized {
public synchronized static void method1() throws InterruptedException {
System.out.println("method1 begin at:" + System.currentTimeMillis());
System.out.println("method1 begin to sleep 5s");
Thread.sleep(5000);
System.out.println("method1 end at:" + System.currentTimeMillis());
}
public synchronized static void method2() throws InterruptedException {
for(int i=0;i<5;i++) {
System.out.println("method2 running");
Thread.sleep(200);
}
}
/**
* 没有static、synchronized修饰的普通方法
* @throws InterruptedException
*/
public void method3() throws InterruptedException {
System.out.println("method3 running");
Thread.sleep(200);
}
/**
* 只有synchronized修饰的普通方法
* @throws InterruptedException
*/
public synchronized void method4() throws InterruptedException {
System.out.println("method4 running");
Thread.sleep(200);
}
static TestSynchronized instance1 = new TestSynchronized();
static TestSynchronized instance2 = new TestSynchronized();
static TestSynchronized instance3 = new TestSynchronized();
static TestSynchronized instance4 = new TestSynchronized();
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
instance1.method1();
//TestSynchronized.mothod1();
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=1; i<4; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread1 still alive");
}
System.out.println("Thread1 over");
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
instance2.method2();
//TestSynchronized.mothod2();
System.out.println("Thread2 over");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
instance3.method3();
System.out.println("method3 over");
Thread.sleep(10000);
System.out.println("Thread3 still alive");
System.out.println("Thread3 now to over");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
try {
instance4.method4();
System.out.println("method4 over");
Thread.sleep(10000);
System.out.println("Thread4 still alive");
System.out.println("Thread4 now to over");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
运行结果:

编程开发之--java多线程学习总结(1)问题引入与概念叙述的更多相关文章
- 编程开发之--java多线程学习总结(5)
4.对继承自Runnable的线程进行锁机制的使用 package com.lfy.ThreadsSynchronize; import java.util.concurrent.locks.Lock ...
- 编程开发之--java多线程学习总结(4)
3.使用锁机制lock,unlock package com.lfy.ThreadsSynchronize; import java.util.concurrent.locks.Lock; impor ...
- 编程开发之--java多线程学习总结(2)同步代码块
1.第一种解决办法:同步代码块,关键字synchronized package com.lfy.ThreadsSynchronize; /** * 1.使用同步代码块 * 语法: synchroniz ...
- 编程开发之--java多线程学习总结(6)
5.测试 package com.lfy.ThreadsSynchronize; public class Test { public static void main(String[] args) ...
- 编程开发之--java多线程学习总结(3)类锁
2.使用方法同步 package com.lfy.ThreadsSynchronize; /** * 1.使用同步方法 * 语法:即用 synchronized 关键字修饰方法(注意是在1个对象中用锁 ...
- Java多线程学习(转载)
Java多线程学习(转载) 时间:2015-03-14 13:53:14 阅读:137413 评论:4 收藏:3 [点我收藏+] 转载 :http://blog ...
- Java多线程学习(三)volatile关键字
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79680693 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- Java多线程学习(一)Java多线程入门
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79640870 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- 转:Java多线程学习(总结很详细!!!)
Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢? 本文主要讲java中多线程 ...
随机推荐
- archiver error. Connect internal only, until freed. 之解决办法
这个报错说的是数据库的日志备份不足空间.解决办法: DELETE backup COMPLETED BEFORE 'SYSDATE-7';DELETE ARCHIVELOG ALL COMPLETED ...
- intval()
1.将字符串转换成整数 2.取数字的整数部分
- [Selenium] 怎样判断是否适合自动化测试
实施自动化测试前需要对软件开发过程进行分析,以观察其是否适合使用自动化测试.通常需要满足以下条件: 1)需求变动不频繁 2)项目周期足够长 3)自动化测试脚本可重复使用 4)手工测试无法完成或者需要大 ...
- Java 设计模式系列(三)抽象工厂
Java 设计模式系列(三)抽象工厂 每天用心记录一点点.内容也许不重要,但习惯很重要!
- python使用smtplib和email发送腾讯企业邮箱邮件
公司每天要发送日报,最近没事搞了一下如何自动发邮件,用的是腾讯企业邮箱,跟大家分享一下我的研究过程吧. 以前弄的发邮件的是用qq邮箱发的,当时在网上查资料最后达到了能发图片,网页,自定义收件人展示,主 ...
- SQL SERVER 2012数据库:开启防火墙导致外部无法连接数据库解决办法
SQL SERVER 2012数据库:开启防火墙导致外部无法连接数据库解决办法 将以下代码存为OpenSqlServerPort.bat文件: netsh advfirewall firewall a ...
- Summary #ToBeContinue......
一.请回望暑假时的第一次作业,你对于软件工程课程的想象1)对比开篇博客你对课程目标和期待,“希望通过实践锻炼,增强计算机专业的能力和就业竞争力”,对比目前的所学所练所得,在哪些方面达到了你的期待和目标 ...
- DE0-Nano-SoC开发板诡异的电源电路方案设计分析
这些日子一直在设计自己的Cyclone V SoC开发板,由于我们这种散兵游勇,是断然没有厂家和代理技术支持的,因此只能找各种现成方案参考.其实Cyclone V SoC芯片的外围电路设计不难,无非就 ...
- handsontable-常用配置
冻结单元格 var //自动创建数据 myData = Handsontable.helper.createSpreadsheetData(100, 50), container = document ...
- 如何注册GitHub
一.个人介绍 姓名:张志龙 学号:1413042026 班级:网工141 爱好:宅物 能力:c++编程 二.注册 注册GitHub其实很简单 首先我们要做的是打开官网 www.github.com(如 ...