java同步代码块和线程安全问题.docx
《java同步代码块和线程安全问题.docx》由会员分享,可在线阅读,更多相关《java同步代码块和线程安全问题.docx(29页珍藏版)》请在冰点文库上搜索。
java同步代码块和线程安全问题
packagecn.itcast.other;
importjava.util.Arrays;
importjava.util.Properties;
/*
System系统类主要用于获取系统的属性数据。
System类常用的方法:
arraycopy(Objectsrc,intsrcPos,Objectdest,intdestPos,intlength)一般
src-源数组。
srcPos-源数组中的起始位置。
dest-目标数组。
destPos-目标数据中的起始位置。
length-要复制的数组元素的数量。
currentTimeMillis()获取当前系统系统。
重点
exit(intstatus)退出jvm如果参数是0表示正常退出jvm,非0表示异常退出jvm。
一般
gc()建议jvm赶快启动垃圾回收期回收垃圾。
getenv(Stringname)根据环境变量的名字获取环境变量。
getProperty(key)
finalize()如果一个对象被垃圾回收器回收的时候,会先调用对象的finalize()方法。
*/
classPerson{
Stringname;
publicPerson(Stringname){
this.name=name;
}
@Override
publicvoidfinalize()throwsThrowable{
super.finalize();
System.out.println(this.name+"被回收了..");
}
}
publicclassDemo1{
publicstaticvoidmain(String[]args){
/*
int[]srcArr={10,12,14,16,19};
//把srcArr的数组元素拷贝到destArr数组中。
int[]destArr=newint[4];
System.arraycopy(srcArr,1,destArr,0,4);
//System.exit(0);//jvm退出..注意:
0或者非0的数据都可以退出jvm。
对于用户而言没有任何区别。
System.out.println("目标数组的元素:
"+Arrays.toString(destArr));//014160
System.out.println("当前的系统时间:
"+System.currentTimeMillis());
System.out.println("环境变量:
"+System.getenv("JAVA_HOME"));
for(inti=0;i<4;i++){
newPerson("狗娃"+i);
System.gc();//建议马上启动垃圾回收期
}
Propertiesproperties=System.getProperties();//获取系统的所有属性。
properties.list(System.out);
*/
Stringvalue=System.getProperty("os.name");//根据系统的属性名获取对应的属性值
System.out.println("当前系统:
"+value);
}
}
packagecn.itcast.other;
importjava.io.IOException;
importjavax.management.RuntimeErrorException;
/*
RunTime该类类主要代表了应用程序运行的环境。
getRuntime()返回当前应用程序的运行环境对象。
exec(Stringcommand)根据指定的路径执行对应的可执行文件。
freeMemory()返回Java虚拟机中的空闲内存量。
。
以字节为单位
maxMemory()返回Java虚拟机试图使用的最大内存量。
totalMemory()返回Java虚拟机中的内存总量
*/
publicclassDemo2{
publicstaticvoidmain(String[]args)throwsIOException,InterruptedException{
Runtimeruntime=Runtime.getRuntime();
//Processprocess=runtime.exec("C:
\\Windows\\notepad.exe");
//Thread.sleep(3000);//让当前程序停止3秒。
//process.destroy();
System.out.println("Java虚拟机中的空闲内存量。
"+runtime.freeMemory());
System.out.println("Java虚拟机试图使用的最大内存量:
"+runtime.maxMemory());
System.out.println("返回Java虚拟机中的内存总量:
"+runtime.totalMemory());
}
}
packagecn.itcast.other;
importjava.text.ParseException;
importjava.text.SimpleDateFormat;
importjava.util.Calendar;
importjava.util.Date;
/*
日期类Date
Calendar
日期格式化类SimpleDateFormat
*/
publicclassDemo3{
publicstaticvoidmain(String[]args)throwsParseException{
/*Datedate=newDate();//获取当前的系统时间
System.out.println("年份:
"+date.getYear());*/
/*
Calendarcalendar=Calendar.getInstance();//获取当前的系统时间。
System.out.println("年:
"+calendar.get(Calendar.YEAR));
System.out.println("月:
"+(calendar.get(Calendar.MONTH)+1));
System.out.println("日:
"+calendar.get(Calendar.DATE));
System.out.println("时:
"+calendar.get(Calendar.HOUR_OF_DAY));
System.out.println("分:
"+calendar.get(Calendar.MINUTE));
System.out.println("秒:
"+calendar.get(Calendar.SECOND));
//显示当前系统时间:
2014年12月26日xx时xx分xx秒
*日期格式化类SimpleDateFormat
*作用1:
可以把日期转换转指定格式的字符串format()
*作用2:
可以把一个字符转换成对应的日期。
parse()生日
*
*/
Datedate=newDate();//获取当前的系统时间。
SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy年MM月dd日HH:
mm:
ss");//使用了默认的格式创建了一个日期格式化对象。
Stringtime=dateFormat.format(date);//可以把日期转换转指定格式的字符串
System.out.println("当前的系统时间:
"+time);
Stringbirthday="2000年12月26日11:
29:
08";
Datedate2=dateFormat.parse(birthday);//注意:
指定的字符串格式必须要与SimpleDateFormat的模式要一致。
System.out.println(date2);
Datedate21=newDate();
SimpleDateFormatdateFormat2=newSimpleDateFormat("yyyy年MM月dd日HH:
mm:
ss");
Stringtime2=dateFormat.format(date21);
Stringtime21=dateFormat.format(date);
System.out.println("当前的系统时间:
"+time);
Stringbirthday1="2000年12月26日11:
28:
08";
Datedate22=dateFormat.parse(birthday1);
System.out.println(date22);
}
}
packagecn.itcast.other;
/*
Math数学类,主要是提供了很多的数学公式。
abs(doublea)获取绝对值
ceil(doublea)向上取整
floor(doublea)向下取整
round(floata)四舍五入
random()产生一个随机数.大于等于0.0且小于1.0的伪随机double值
*/
publicclassDemo4{
publicstaticvoidmain(String[]args){
System.out.println("绝对值:
"+Math.abs(-3));
System.out.println("向上取整:
"+Math.ceil(3.14));
System.out.println("向下取整:
"+Math.floor(-3.14));//
System.out.println("四舍五入:
"+Math.round(3.54));
System.out.println("随机数:
"+Math.random());
}
}
packagecn.itcast.other;
importjava.util.Random;
/*
随机数类
Random
需求:
编写一个函数随机产生四位的验证码。
*/
publicclassDemo5{
publicstaticvoidmain(String[]args){
/*
Randomrandom=newRandom();
intrandomNum=random.nextInt(10)+1;//产生的随机数就是0-10之间
System.out.println("随机数:
"+randomNum);
*/
char[]arr={'中','国','传','a','Q','f','B'};
StringBuildersb=newStringBuilder();
Randomrandom=newRandom();
//需要四个随机数,通过随机数获取字符数组中的字符,
for(inti=0;i<4;i++){
intindex=random.nextInt(arr.length);//产生的随机数必须是数组的索引值范围之内的。
sb.append(arr[index]);
}
System.out.println("验证码:
"+sb);
}
}
packagecn.itcast.stringbuffer;
/*
字符串特点:
字符串是常量;它们的值在创建之后不能更改.
字符串的内容一旦发生了变化,那么马上会创建一个新的对象。
注意:
字符串的内容不适宜频繁修改,因为一旦修改马上就会创建一个新的对象。
如果需要频繁修改字符串的内容,建议使用字符串缓冲类(StringBuffer)。
StringBuffer其实就是一个存储字符的容器。
*/
publicclassDemo1{
publicstaticvoidmain(String[]args){
Stringstr1="hello";
Stringstr2=str1+"world";
System.out.println("str1与str2是同一个对象吗?
"+(str1==str2));
}
}
packagecn.itcast.stringbuffer;
/*
如果需要频繁修改字符串的内容,建议使用字符串缓冲类(StringBuffer)。
StringBuffer其实就是一个存储字符的容器。
笔试题目:
使用Stringbuffer无参的构造函数创建一个对象时,默认的初始容量是多少?
如果长度不够使用了,自动增长多少倍?
StringBuffer底层是依赖了一个字符数组才能存储字符数据的,该字符串数组默认的初始容量是16,如果字符数组的长度不够使用死,自动增长1倍。
StringBuffer是一个存储字符的容器
容器的具备的行为
String
增加
append(booleanb)可以添加任意类型的数据到容器中
insert(intoffset,booleanb)指定插入的索引值,插入对应的内容。
删除
delete(intstart,intend)根据指定的开始与结束的索引值删除对应的内容。
deleteCharAt(intindex)根据指定的索引值删除一个字符。
修改
replace(intstart,intend,Stringstr)根据指定的开始与结束索引值替代成指定的内容。
reverse()翻转字符串缓冲类的内容。
abc--->cba
setCharAt(intindex,charch)把指定索引值的字符替换指定的字符。
substring(intstart,intend)根据指定的索引值截取子串。
ensureCapacity(intminimumCapacity)指定StringBuffer内部的字符数组长度的。
查看
indexOf(Stringstr,intfromIndex)查找指定的字符串第一次出现的索引值,并且指定开始查找的位置。
lastIndexOf(Stringstr)
capacity()查看当前字符数组的长度。
length()
charAt(intindex)
toString()把字符串缓冲类的内容转成字符串返回。
StringBuffer与StringBuilder的相同处与不同处:
相同点:
1.两个类都是字符串缓冲类。
2.两个类的方法都是一致的。
不同点:
1.StringBuffer是线程安全的,操作效率低,StringBuilder是线程非安全的,操作效率高。
2.StringBuffer是jdk1.0出现的,StringBuilder是jdk1.5的时候出现的。
推荐使用:
StringBuilder,因为操作效率高。
*/
publicclassDemo2{
publicstaticvoidmain(String[]args){
//先使用StringBuffer无参的构造函数创建一个字符串缓冲类。
StringBuffersb=newStringBuffer();
sb.append("abcjavaabc");
/*
添加
sb.append(true);
sb.append(3.14f);
插入
sb.insert(2,"小明");
*/
/*
删除
sb.delete(2,4);//删除的时候也是包头不包尾
sb.deleteCharAt(3);//根据指定的索引值删除一个字符
修改
sb.replace(2,4,"陈小狗");
sb.reverse();//翻转字符串的内容
sb.setCharAt(3,'红');
StringsubString=sb.substring(2,4);
System.out.println("子串的内容:
"+subString);
查看
intindex=sb.indexOf("abc",3);
System.out.println("索引值为:
"+index);
sb.append("javajava");
System.out.println("查看字符数组的长度:
"+sb.capacity());
*/
System.out.println("存储的字符个数:
"+sb.length());
System.out.println("索引指定的索引值查找字符:
"+sb.charAt
(2));
System.out.println("字符串缓冲类的内容:
"+sb);
Stringcontent=sb.toString();
test(content);
}
publicstaticvoidtest(Stringstr){
}
}
packagecn.itcast.thread;
/*
进程:
正在执行的程序称作为一个进程。
进程负责了内存空间的划分。
问题:
windows号称是多任务的操作系统,那么windows是同时运行多个应用程序吗?
从宏观的角度:
windows确实是在同时运行多个应用程序。
从微观角度:
cpu是做了一个快速切换执行的动作,由于速度态度,所以我感觉不到在切换而已。
线程:
线程在一个进程中负责了代码的执行,就是进程中一个执行路径,
多线程:
在一个进程中有多个线程同时在执行不同的任务。
疑问:
线程负责了代码的执行,我们之前没有学过线程,为什么代码可以执行呢?
运行任何一个java程序,jvm在运行的时候都会创建一个main线程执行main方法中所有代码。
一个java应用程序至少有几个线程?
至少有两个线程,一个是主线程负责main方法代码的执行,一个是垃圾回收器线程,负责了回收垃圾。
多线程的好处:
1.解决了一个进程能同时执行多个任务的问题。
2.提高了资源的利用率。
多线程的弊端:
1.增加cpu的负担。
2.降低了一个进程中线程的执行概率。
3.引发了线程安全问题。
4.出现了死锁现象。
如何创建多线程:
创建线程的方式:
方式一:
1.自定义一个类继承Thread类。
2.重写Thread类的run方法,把自定义线程的任务代码写在run方法中
疑问:
重写run方法的目的是什么?
每个线程都有自己的任务代码,jvm创建的主线程的任务代码就是main方法中的所有代码,自定义线程的任务代码就写在run方法中,自定义线程负责了run方法中代码。
3.创建Thread的子类对象,并且调用start方法开启线程。
注意:
一个线程一旦开启,那么线程就会执行run方法中的代码,run方法千万不能直接调用,直接调用run方法就相当调用了一个普通的方法而已
并没有开启新的线程。
*/
publicclassDemo1extendsThread{
@Override//把自定义线程的任务代码写在run方法中。
publicvoidrun(){
for(inti=0;i<100;i++){
System.out.println("自定义线程:
"+i);
}
}
publicstaticvoidmain(String[]args){
//创建了自定义的线程对象。
Demo1d=newDemo1();
//调用start方法启动线程
d.start();
for(inti=0;i<100;i++){
System.out.println("main线程:
"+i);
}
}
}
packagecn.itcast.thread;
/*
需求:
模拟QQ视频与聊天同时在执行。
*/
classTalkThreadextendsThread{
@Override
publicvoidrun(){
while(true){
System.out.println("hi,你好!
开视频呗...");
}
}
}
classVideoThreadextendsThread{
@Override
publicvoidrun(){
while(true){
System.out.println("视频视频....");
}
}
}
publicclassDemo2{
publicstaticvoidmain(String[]args){
TalkThreadtalkThread=newTalkThread();
talkThread.start();
VideoThreadvideoThread=newVideoThread();
videoThread.start();
}
}
packagecn.itcast