Java基础8-多线程;同步代码块
作业解析
利用白富美接口案例,土豪征婚使用匿名内部类对象实现。
interface White{
public void white();
} interface Rich{
public void rich();
} interface Beauty{
public void beauty();
} interface WRB extends White, Rich, Beauty{
} class TuHao{
public void getMarry(WRB wrb){
wrb.white();
wrb.rich();
wrb.beauty();
}
} class Demo{
public static void main(String[] args){
TuHao wsc = new TuHao();
wsc.getMarry(new WRB(){
public void white(){
System.out.println("white");
}
public void rich(){
System.out.println("rich");
}
public void beauty(){
System.out.println("beauty");
}
});
}
}定义三角形类Trianle,里面包含三个int类型属性,分别表示三条边的长度,
构造三角形对象时,任意两边之和是否大于第三边,如若不成立,抛出自定义异常。class Triangle{
private int a;
private int b;
private int c;
public Triangle(int a, int b, int c){
try{
if(a>=b+c || b>=a+c || c>=a+b){
throw new TriangleLengthException("Invalid Length");
}
else{
this.a = a;
this.b = b;
this.c = c;
}
}
catch(TriangleLengthException e){
e.printStackTrace();
}
}
} class TriangleLengthException extends Exception{
String exceptionInfo;
public TriangleLengthException(String info){
exceptionInfo = info;
} public void printStackTrace(){
System.out.println(exceptionInfo);
}
} class TriExceptionDemo{
public static void main(String[] args){
Triangle t1 = new Triangle(2,3,4);
Triangle t2 = new Triangle(2,2,4);
Triangle t3 = new Triangle(2,7,4);
}
}Person类中增加birthday属性,对setBirthday(int ,int , int )方法进行异常处理,
要求年有效、月有效、日有效、年月日指定的具体日期有效,对不同情况分别抛出不同的异常。
year:>1970, month:1-12, day:1-31class Person{
private int year;
private int month;
private int day;
public void setBirthday(int year, int month, int day){
try{
if(year<1970){
throw new YearException("Invalid Year");
}
else{
if(month<1 || month > 12){
throw new MonthException("Invalid Month");
}
else{
if(day<1 || day>31){
throw new DayException("Invalid Day");
}
else{
switch(month){
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
break;
case 2:
if((year%400==0) || (year%4==0 && year%100!=0)){
if(day>29){
throw new DateException("Invalid Date");
}
}
else{
if(day>28){
throw new DateException("Invalid Date");
}
}
case 4:
case 6:
case 9:
case 11:
if(day==31){
throw new DateException("Invalid Date");
}
}
}
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
} class YearException extends Exception{
String exceptionInfo;
public YearException(String info){
exceptionInfo = info;
}
public void printStackTrace(){
System.out.println(exceptionInfo);
}
} class MonthException extends Exception{
String exceptionInfo;
public MonthException(String info){
exceptionInfo = info;
}
public void printStackTrace(){
System.out.println(exceptionInfo);
}
} class DayException extends Exception{
String exceptionInfo;
public DayException(String info){
exceptionInfo = info;
}
public void printStackTrace(){
System.out.println(exceptionInfo);
}
} class DateException extends Exception{
String exceptionInfo;
public DateException(String info){
exceptionInfo = info;
}
public void printStackTrace(){
System.out.println(exceptionInfo);
}
} class BirthdayExceptionDemo{
public static void main(String[] args){
Person p1 = new Person();
p1.setBirthday(12,1,22);
p1.setBirthday(1970,13,22);
p1.setBirthday(2000,1,32);
p1.setBirthday(2000,2,28);
p1.setBirthday(2000,2,29);
p1.setBirthday(2016,2,30);
p1.setBirthday(2100,2,29);
}
}将类定义到指定的包下。com.xkzhai.jar,编译之后,打成jar文件。
编写源文件jarDemo.java
package com.xkzhai.jar;
class Person{
private String name;
private String sex;
public void run(){
System.out.println("run");
}
} class jarDemo{
public static void main(String[] args){
Person p1 = new Person();
p1.run();
}
}编译到指定的位置
javac -d classes2 jarDemo.java归档
jar cvf test.jar -C classes2/ .
jar cvfe test2.jar com.xkzhai.jar.jarDemo -C classes2/ . //在清单文件中增加入口点运行程序
java -cp classes2 com.xkzhai.jar.jarDemo
java -cp test.jar com.xkzhai.jar.jarDemo
java -jar test2.jar//定义好入口点的jar包
相互之间使用jar包,放置cp下,对class进行重用
编写第一个java程序Person.java
package com.xkzhai.jar1;
//不同包下的类重用,需定义为public
public class Person{
private String name;
private String sex;
private int age;
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
}编译上述文件,放置到classes3文件夹下
javac -d classes3 Person.java将类文件打包归档为jar1.jar,放置在lib文件夹下
jar cvf jar1.jar -C classes3/ .重用Person类,编写第二个java程序jarDemo2.java,放置在src文件夹下
package cn.xkzhai;
import com.xkzhai.jar1.Person;
class Student extends Person{
private String ID;
} class jarDemo2{
public static void main(String[] args){
Student s1 = new Student();
s1.setAge(20);
System.out.println(s1.getAge());
}
}编译jarDemo2.java,生成的类文件放置在classes中
javac -cp lib/jar1.jar -d classes src/jarDemo2.java执行
java -cp lib/jar1.jar;classes cn.xkzhai.jarDemo2
设计程序,考查修饰符。public -> protected -> default -> private(选做题)
编写ArrayTool,把冒泡排序,选择排序,二分法查找等打成jar包。
编写java源文件ArrayTool3.java
package com.xkzhai.array; class ArrayTool3{
int[] arrayData; public ArrayTool3(){
} public ArrayTool3(int[] arrayData){
this.arrayData = arrayData;
} //1. 打印数组元素
public void outArray(){
for(int i: arrayData){
System.out.println(i);
}
} //2. 冒泡排序
// 5 4 3 2 1
// 4 3 2 1 5
// 3 2 1 4 5
// 2 1 3 4 5
// 1 2 3 4 5
public void bubbleSort(){
for(int i = arrayData.length-1;i>0;i--){
for(int j=0;j<i;j++){
if(arrayData[j]>=arrayData[j+1]){
int tmp = arrayData[j];
arrayData[j] = arrayData[j+1];
arrayData[j+1] = tmp;
}
}
}
} //3. 选择排序
//5 4 3 2 1
//1 5 4 3 2
//1 2 5 4 3
//1 2 3 5 4
//1 2 3 4 5
public void selectSort(){
for(int i=0;i<arrayData.length-1;i++){
for(int j=i;j<=arrayData.length-1;j++){
if(arrayData[j]<=arrayData[i]){
int tmp = arrayData[j];
arrayData[j] = arrayData[i];
arrayData[i] = tmp;
}
}
}
} //4. 选择排序
public int halfFind(int c){
int min = 0;
int max = arrayData.length-1;
int index = 0; while(min<=max){
index = (min+max)/2;
if(arrayData[index]>c){
max = index-1;
}
else if(arrayData[index]<c){
min = index+1;
}
else{
return index;
}
}
return -1;
}
} class ArrayDemo{
public static void main(String[] args){
ArrayTool3 arr = new ArrayTool3(new int[]{1,3,2,20,12});
arr.outArray();
arr.bubbleSort();
arr.outArray(); ArrayTool3 arr2 = new ArrayTool3(new int[]{1,3,2,20,12,23,21,19});
arr2.outArray();
arr2.selectSort();
arr2.outArray();
System.out.println(arr2.halfFind(-1));
System.out.println(arr2.halfFind(12));
}
}编译,打包
javac -d classes4 ArrayTool3.java
//java -cp classes4 com.xkzhai.array.ArrayDemo
jar cvf ArrayTool.jar -C classes4/ .
预习多线程。
进程
运行时(runtime)的应用程序
进程之间的内存不是共享(独占)
进程间通信使用的socket(套接字)
进程之间内存是隔离的。内存不共享。
多线程
程序(进程)执行过程中,并发执行的代码段
线程之间共享内存
创建灵活响应的桌面程序
每个运行着的线程对应一个stack(方法栈)
应用程序至少有一个线程(主线程)
java.lang.Thread
Thread.yield()方法:让当前线程让出CPU抢占权,具有谦逊之意,瞬时的动作
Thread.sleep(int mils)方法:让当前线程休眠指定毫秒数,放弃cpu抢占权,和锁旗标(监控权)没有关系
Thread.join():当前线程等待指定的线程结束后才能继续运行
daemon:守护线程,服务员 Thread.setDaemon(true),为其他线程提供服务的线程。若进程中剩余的线程都是守护线程的话,则进程终止了。
\(--\) 原子性操作
线程间通信,共享资源的问题。锁, 将并行转串行,防止并发访问。参照物,锁旗标
//同步代码块
synchronized(object lock){
...
}
同步代码块执行期间,线程始终持有对象的监控权,其他线程处于阻塞状态,只能等待
同步代码块是以当前所在对象做锁旗标
synchronized(this) === 同步方法同步静态方法,使用类作为同步标记
public static synchronized xxxx(...){
}wait()
让当前线程进入到锁旗标的等待队列,释放cpu抢占权,还释放锁旗标的监控权。
wait(1000); 设定等待时间,可以避免死锁notify()
唤醒在等待队列中的线程,一次只通知一个线程notifyAll()
通知所有线程可以抢占cpu和锁旗标监控权,解决死锁问题class ThreadDemo10{
public static void main(String[] args){ Pool pool = new Pool(); Productor p1 = new Productor("生产者1",pool);
p1.setName("p1");
//Productor p2 = new Productor("生产者2",pool);
Consumer c1 = new Consumer("消费者1",pool);
c1.setName("c1");
Consumer c2 = new Consumer("消费者2",pool);
c2.setName("c2"); p1.start();
//p2.start();
c1.start();
c2.start();
}
} //生产者
class Productor extends Thread{
private String name;
private Pool pool;
static int i = 0; public Productor(String name, Pool pool){
this.name = name;
this.pool = pool;
} public void run(){
//int i=0;
while(true){
pool.add(i++);
}
}
} //消费者
class Consumer extends Thread{
private String name;
private Pool pool;
public Consumer(String name, Pool pool){
this.name = name;
this.pool = pool;
} public void run(){
while(true){
pool.remove();
}
}
} //票池
class Pool{
private java.util.List<Integer> list = new java.util.ArrayList<Integer>();
//容器最大值
private int MAX = 1; //添加元素
public void add(int n){ synchronized(this){
try{
String name = Thread.currentThread().getName();
while(list.size() == MAX){
System.out.println(name+".wait()");
this.wait();
}
list.add(n);
System.out.println(name+"+: "+n);
System.out.println(name+".notify()");
this.notifyAll();
}
catch(Exception e){
e.printStackTrace();
}
}
} //删除元素
public int remove(){ synchronized(this){
try{
String name = Thread.currentThread().getName();
while(list.size() == 0){
System.out.println(name+".wait()");
this.wait();
}
int i = list.remove(0);
System.out.println(name+"-:"+i);
System.out.println(name+".notify()");
this.notifyAll();
return i;
}
catch(Exception e){
e.printStackTrace();
}
return -1;
}
}
}
作业
一共100个馒头,40个工人,每个工人最多能吃3个馒头,使用多线程输出所有工人吃馒头的情况
5辆汽车过隧道,隧道一次只能通过一辆汽车。每辆汽车通过时间不固定,
机动车通过时间3秒,三轮车通过时间5秒,畜力车通过时间10秒,5辆车分别是2辆机动车,2辆畜力车,1辆三轮车,通过多线程模拟通过隧道的情况。提示:Car ThreeCar CowCar用多线程模拟蜜蜂和熊的关系
蜜蜂是生产者,熊是消费者,蜜蜂生产蜂蜜是累加的过程,熊吃蜂蜜是批量(满20吃掉)的过程,生产者和消费者之间使用通知方式告知对方,注意不能出现死锁现象。
100只蜜蜂,每次生产的蜂蜜是1
熊吃蜂蜜是20(批量的情况)
Java基础8-多线程;同步代码块的更多相关文章
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this
JAVA之旅(十三)--线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this 我们继续上个篇幅接着讲线程的知识点 一.线程的安全性 当我们开启四个窗口(线程 ...
- Java多线程同步代码块
/*多线程的安全问题1.为什么会出现安全问题?因为程序在运行时,会出现一个线程在判断条件满足后,具备了执行资格,但没有运行代码后一个线程也判断了条件,也具备了执行资格,后一个线程运行了代码,但这时候, ...
- java中的synchronized同步代码块和同步方法的区别
下面这两段代码有什么区别? //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized ...
- 夯实Java基础(八)——代码块
在Java中代码块指的是使用”{}”括起来的代码称为代码块.代码块一共分为4种:局部代码块,静态代码块,同步代码块,构造代码块. 1.局部代码块 局部代码块就是定义在方法体内部的代码块. public ...
- java的同步方法和同步代码块,对象锁,类锁区别
/** * @author admin * @date 2018/1/12 9:48 * 作用在同一个实例对象上讨论 * synchronized同步方法的测试 * 两个线程,一个线程调用synchr ...
- Java的synchronized的同步代码块和同步方法的区别
synchronized同步方法和同步代码块的区别 同步方法默认使用this或者当前类做为锁. 同步代码块可以选择以什么来加锁,比同步方法更精确,我们可以选择只有会在同步发生同步问题的代码加锁,而并不 ...
- java基础入门-多线程同步浅析-以银行转账为样例
在说之前先普及一下线程是什么? 线程:说白了就是一个任务片段 进程:是一个具有独立功能的程序关于某个数据集合的一次执行活动.一个进程有一个或者多个线程 线程与进程的本质差别就是有么有数据共享空间.线程 ...
- “全栈2019”Java多线程第二十一章:同步代码块产生死锁的例子
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
随机推荐
- 山东省网络安全技能大赛 部分writeup
web1 提示:ip不在范围内 直接抓包加client-ip: 127.0.0.1 即可得到flag web2 <?php include 'here.php'; $key = 'kela ...
- PWC6345: There is an error in invoking javac. A full JDK (not just JRE) is required
今天在使用jetty运行一个项目的时候报这个错误,仔细看了下,应该是eclipse配置的jdk或者jre出错. 看了下环境变量,发现有些配置没有配置完全. 我个人的解决方法: 在path中,添加%JA ...
- 最速下降方法和Newton方法
目录 最速下降方法 Euclid范数和二次范数 采用\(\ell_1\)-范数的最速下降方向 Newton 方法 Newton 步径 二阶近似的最优解 线性化最优性条件的解 Newton 步径的仿射不 ...
- Kubernetes — Job与CronJob
有一类作业显然不满足这样的条件,这就是“离线业务”,或者叫作 Batch Job(计算业务). 这 种业务在计算完成后就直接退出了,而此时如果你依然用 Deployment 来管理这种业务的话,就会 ...
- sql 日常使用记录
sql 某个字段在哪些表中存在: select sysobjects.name from syscolumns inner join sysobjects on syscolumns.id = sys ...
- 《Effective C++》实现:条款26-条款31
条款26:尽可能延后变量定义式的出现时间 C++推荐在使用对象前才定义对象(调用构造函数赋初值) 只在循环中使用的变量定义在循环内部(除非"赋值"成本低于"构造+析构&q ...
- OOM分析工具
OOM (OutOfMemoryError) 1.MAT工具 在eclipse中安装.Help>Eclipse Marketplace 搜索MAT 接下来运行程序,run configratio ...
- Python——Flask框架——电子邮件
一.框架(Flask-Mail) 安装 : pip install flask-mail 二.SMTP服务器的配置 配置 默认值 说明 MAIL_SERVER locallhost 电子邮件服务器的主 ...
- 语义SLAM研究现状总结
博客转载自:https://blog.csdn.net/xiaoxiaowenqiang/article/details/81051010 原文标题:深度学习结合SLAM 语义slam 语义分割 端到 ...
- Linux 学习 (七) 挂载命令 & 用户登陆查看
Linux达人养成计划 I 学习笔记 挂载命令 mount:查询系统中已经挂载的设备 mount -a:根据配置文件 /etc/fstab 的内容,自动挂载 mount [-t 文件系统] [-o 特 ...