title: Java 学习笔记
date: 2017-06-23 11:29:39
Mac配置java环境
- 第一步: vi .zshrc
- 第二步: 将这段文字输入 export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH - 第三步: 输入source .zshrc 这样就可以使得环境变量起作用了
- 第四步: echo $JAVA_HOME看看有没有输出刚才配置的路径
Class JavaLaunchHelper is implemented in both... 报错处理
// Go to ➤ (Help | Edit Custom Properties...)
idea_rt
idea.no.launcher=true
创建一个简单的demo
一. 打开textEdit软件 设置:preferences > Format > Plain text 创建hello.java文件
``` java
public class hello{
public static void main(String[] args){
System.out.println("hello world");
}
}
```
二. 找到当前文件目录 注意文件夹名字和类名一致(源程序)
javac hello.java
三. 生成一个hello.class的文件,然后执行(字节码程序)
java hello
乘法口诀
// i 代表行数
for(int i=1;i<=9;i++){
for(int j=1;j<=i;j++){
System.out.print(j + " * " + i + " = " + (i*j) + "\t");
}
System.out.println()
}
Java数组的可变参数
public class app {
public static void main(String[] args) {
// 第一种传递数组
double[] arr1 = {10.0, 23.0, 12.0, 13};
double sum = getSum(arr1);
// 第二种传递方式(可变参数)
double sum = getSum(0.8, 123.0, 2341, 3, 3.0); //单个放在前面,避免歧义
System.out.println(sum);
}
static double getSum(double cutoff, double... arr) {
double sum = 0;
for (double price : arr) {
sum += price * cutoff;
}
return sum;
}
}
java.util.Arrays 工具
public class array {
public static void main(String[] args) {
int[] arr = {1, 34, 5, 5, 65, 7, 76, 33};
// 打印
String arrString = java.util.Arrays.toString(arr);
System.out.println(arrString);
// 排序
java.util.Arrays.sort(arr, 2, 6);
System.out.println(java.util.Arrays.toString(arr));
// 二分法
int index = java.util.Arrays.binarySearch(arr,5);
System.out.println(index);
}
}
java中的变量(成员变量和局部变量):
存在位置 | 生命周期开始 | 生命周期结束 | 在内存中的位置 | |
---|---|---|---|---|
类变量 | 字段,使用static修饰 | 当所在字节码被加载进JVM | 当JVM停止 | 方法区 |
实例变量 | 字段,没有使用static修饰 | 当创建类的对象的时候 | 当该对象被GC回收 | 堆 |
局部变量 | 方法形参,代码块中,方法内 | 当代码执行到初始化变量的时候 | 所在的方法/代码块结束 | 当前方法的栈帧中 |
this存在与两个位置。
-构造器中:表示当前创建的对象
-方法中:那个调用this调用的方法,this表示那一个对象
class User {
private String name; // 私有变量默认是null
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name; // this的使用
}
public void showThis (){
System.out.println(this.name);
}
}
public class thisDemo {
public static void main(String[] args) {
// 创建user1对象
User user1 = new User();
user1.setName("lily");
String name = user1.getName();
System.out.println(name);
// 创建user2对象
User user2 = new User();
user2.setName("lucy");
// this的调用
user1.showThis();
user2.showThis();
}
}
面向对象-子类初始化过程
class Animal {
private String name;
private int age;
public void Fly() {
System.out.println("会飞翔");
}
Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
// 继承Animal这个类
class Fish extends Animal {
private String color;
Fish(String name, int age, String color) {
super(name, age); // 父类私有变量赋值
this.color = color;
}
// override 覆盖父类的方法
public void Fly() {
System.out.println("我会游泳");
System.out.println(color + ", " + getName() + super.getAge());
}
}
public class Superdemo {
public static void main(String[] args) {
Fish fish = new Fish("金枪鱼", 5, "yello");
fish.Fly();
String name = fish.getName();
System.out.println(name);
Object obj = "ABC";
// instanceof 判断对象是否是某一个类的实例
System.out.println(obj instanceof Object); //true
System.out.println(obj instanceof String); //true
// getClass()获取对象的实例类型
System.out.println(obj.getClass() == String.class); //true
}
}
包装类的缓存
// 缓存区间[-128,127],超出区间创建一个新空间
// Integer i1 = new Integer(250); //创建一个对象
// Integer i1 = Integer.valueOf(250); // 手动装箱
Integer i1 = 250; // 自动装箱
int i = Integer.valueOf(i1); //拆箱
String str = String.valueOf(i1); //数字转字符串
int num = Integer.parseInt(str); // 字符串转数字
Integer i2 = 250;
System.out.println(i1 == i2); //false
System.out.println(i1.equals(i2)); //true
模版方法的设计
// 模版方法
abstract class TemplateFn {
// 算法的骨架
final public long getTime() {
long beginTime = System.currentTimeMillis();
// callback
dowork();
long endime = System.currentTimeMillis();
return endime - beginTime;
}
// 子类必须覆盖
protected abstract void dowork();
}
// 拼接字符串
class StringDemo extends TemplateFn {
protected void dowork() {
String str = "";
for (int i = 0; i < 10000; i++) {
str += i;
}
}
}
// 加法
class AddNumDemo extends TemplateFn {
protected void dowork() {
int sum = 0;
for (int i = 0; i < 10000; i++) {
sum += 1;
}
}
}
public class TemplateDemo {
public static void main(String[] args) {
System.out.println(new StringDemo().getTime());
System.out.println(new AddNumDemo().getTime());
}
}
单例方法和枚举方法运用
// 单例模式
class Arrays {
/**
* 1.必须在该类中创建一个对象
* 2.私有化自身的构造器
* 3.暴露自己的一个方法
*/
private static Arrays arrays = new Arrays();
private Arrays() {
}
public static Arrays getArrays() {
return arrays;
}
public void sort(int[] a) {
System.out.println("数字排序成功");
}
}
// 枚举代替单例
enum Arrays {
arrays;
public void sort(int[] a) {
System.out.println("数字排序成功");
}
}
public class human {
public static void main(String[] args) {
// 单例方法
Arrays.getArrays().sort(null);
// 枚举方法
Arrays.arrays.sort(null);
}
}
日期格式化(SimpleDateFormat、Calendar)
//SimpleDateFormat格式化日期
package com.controller;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateformatDemo {
public static void main(String[] args) {
Date d = new Date();
System.out.println(d);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
System.out.println(df.format(d));
try {
System.out.println(df.parse("2017-07-28 17:52:32 Fri"));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
//Calendar创建日期
import java.util.Calendar;
import java.util.Date;
public class CalendarDemo {
public static void main(String[] args) {
//创建日历对象
Calendar c = Calendar.getInstance();
System.out.println(c);
System.out.println("年"+c.get(Calendar.YEAR));
System.out.println("月"+(c.get(Calendar.MONTH)+1));
System.out.println("日"+c.get(Calendar.DATE));
System.out.println("时"+c.get(Calendar.HOUR_OF_DAY));
System.out.println("分"+c.get(Calendar.MINUTE));
System.out.println("秒"+c.get(Calendar.SECOND));
// Calendar 转换成 Date
Date d = c.getTime();
System.out.println(d);
// 给指定的日期添加和减去指定的时间量
c.add(Calendar.DATE,1);
System.out.println(c.getTime());
}
}
Scanner获取用户的输入。
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("next方式接收");
// 判断是否还有输入
if (scanner.hasNext()) {
String str1 = scanner.nextLine();
System.out.println("输入的数据为:" + str1);
}
/**
* 输入平均数
*/
Scanner scan = new Scanner(System.in);
double sum = 0;
int m = 0;
while (scan.hasNextDouble()) {
double x = scan.nextDouble();
m += 1;
sum += x;
}
System.out.println(m + "个数的和为" + sum);
System.out.println(m + "个数的平均值是" + (sum / m));
}
}
Runtime和ProcessBuilder运行环境
import java.io.IOException;
public class ProcessDemo {
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime();
runtime.exec("ifconfig");
ProcessBuilder ps = new ProcessBuilder("ifconfig");
ps.start();
}
}
Java 流(Stream)、文件(File)和IO
import java.io.*;
public class FileSreamDemo {
//删除文件及目录
public static void deleteFolder(File folder) {
File[] files = folder.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
deleteFolder(f);
} else {
f.delete();
}
}
}
folder.delete();
}
public static void main(String args[]) {
/**
* 创建目录
*/
String dirname = "/tmp/user/java/bin";
File dir = new File(dirname);
dir.mkdirs();
/**
* 删除目录
*/
File d = new File("/tmp/user/java/bin");
deleteFolder(d);
try {
/**
* 写入数据
*/
FileOutputStream fop = new FileOutputStream("test.txt");
OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8");
byte[] bWrite = {1, 3, 4, 5, 6};
for (int i = 0; i < bWrite.length; i++) {
System.out.println(new String(String.valueOf(bWrite[i])));
writer.append(String.valueOf(bWrite[i]));
}
writer.close(); // 关闭读取流
fop.close(); // 关闭输入流,释放系统资源
/**
* 读数据
*/
FileInputStream fip = new FileInputStream("test.txt");
InputStreamReader reader = new InputStreamReader(fip, "UTF-8");
StringBuffer sb = new StringBuffer();
while (reader.ready()) {
sb.append((char) reader.read());
// 转成char加到StringBuffer对象中
}
System.out.println(sb.toString());
reader.close();
fip.close();
} catch (IOException e) {
System.out.print("Exception");
}
}
}
Map集合中的keyset方法遍历(LinkedHashMap,HashMap)
public class MapDemo {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
// 添加值
map.put("a", 1);
map.put("b", 1);
map.put("c", 1);
// 删除值
map.remove("c");
System.out.println(map);
// 获取值
System.out.println(map.get("a"));
/**
* 1.调用map的ketset方法所有的集合存到set集合中
* 2。遍历set,获取每个元素
* 3。调用get方法,获取每个对应的值
*/
Set<String> set = map.keySet();
System.out.println(set.getClass());
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String key = it.next();
Integer value = map.get(key);
System.out.println(key + "..." + value);
}
for (String i : map.keySet()) {
Integer value = map.get(i);
System.out.println(i + "..." + value);
}
/**
* 1。调用map中的entrySet将集合中的集合映射关系,存储到Set集合
* 2。迭代set集合
* 3。获取集合元素是映射关系
* 4。通过映射对象方法getkey,getValue获取健值对
*/
Set<Map.Entry<String, Integer>> entryset = map.entrySet();
Iterator<Map.Entry<String, Integer>> it = entryset.iterator();
while (it.hasNext()) {
Map.Entry<String, Integer> entry = it.next();
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + "..." + value);
}
for(Map.Entry<String, Integer> entry:map.entrySet()){
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + "..." + value);
}
}
}
Java IO file的用法
import java.io.File;
import java.io.IOException;
public class javaIOdemo {
public static void main(String[] args) {
File file = new File("/Users/shangri-la/Sites");
String pathSeparator = File.pathSeparator;
String separator = File.separator;
File file1 = new File("/Users", "shangri-la/Sites");
System.out.println(file1); // /Users/shangri-la/Sites
System.out.println(pathSeparator); // :
System.out.println(separator); // /
System.out.println(file); // /Users/shangri-la/Sites
try {
creatFile();
mkDir();
} catch (IOException e) {
e.printStackTrace();
}
delete();
getName();
getFiles();
}
// 创建文件
public static void creatFile() throws IOException {
File file = new File("/Users/shangri-la/Sites/a.txt");
//只能创建文件,不能创建文件夹
boolean b = file.createNewFile();
System.out.println(b);
}
/**
* 创建文件
* mkdir
* mkdirs 创建多文件夹
*
* @throws IOException
*/
public static void mkDir() throws IOException {
File file = new File("/Users/shangri-la/Sites/abc");
boolean b = file.mkdirs();
System.out.println(b);
}
/**
* 删除文件/文件夹
*
* @throws IOException
*/
public static void delete() {
File file = new File("/Users/shangri-la/Sites/abc");
boolean b = file.delete();
System.out.println(b);
}
/**
* String getName()
* 获取文件夹/文件名字
* String path 获取字符串路径
* long length
* Srting getAbsoluteFile() 获取绝对路径 String
* File getAbsoluteFile() 获取绝对路径 File
* String getParent 获取父路径
* File getParentFile 获取父路径
* boolean exists 判断路径是否存在
* boolean isDirectory 判断是不是文件夹
* boolean isFile 判断是不是文件夹
*/
public static void getName() {
File file = new File("/Users/shangri-la/Sites/abc.text");
String name = file.getName();
String path = file.getPath();
Long lenth = file.length();
File absolutefile = file.getAbsoluteFile();
System.out.println(name);
System.out.println(absolutefile);
System.out.println(path);
System.out.println(lenth);
File parentFile = file.getParentFile().getParentFile().getParentFile().getParentFile();
System.out.println(parentFile);
Boolean b = file.exists();
Boolean c = file.isFile();
System.out.println(b);
}
public static void getFiles() {
File file = new File("/Users/shangri-la/Sites");
String[] fileNames = file.list();
for (String fileName : fileNames) {
System.out.println(fileName);
}
}
}
FileFilter过滤器
// 1.创建DirectoryDome过滤器文件
import java.io.File;
import java.io.FileFilter;
/**
* FileFilter过滤器
*/
public class DirectoryDome implements FileFilter {
public boolean accept(File pathname) {
if (pathname.isDirectory())
return true;
return pathname.getName().toLowerCase().endsWith(".java");
}
}
// 2.创建MyFilterDemo主函数文件
import filter.DirectoryDome;
import java.io.File;
public class MyFilterDemo {
public static void main(String[] args) {
getAllJava(new File("/Users/shangri-la/Sites"));
}
public static void getAllJava(File dir) {
File[] files = dir.listFiles(new DirectoryDome()); //添加过滤器
for (File f : files) {
if (f.isDirectory()) {
getAllJava(f);
} else {
if ("b.java".equals(f.getName()))
System.out.println(f.getName());
}
}
}
}
FileOutputStream输出流的用法
import java.io.FileOutputStream;
public class FileOutputStreamDemo {
public static void main(String[] args) throws Exception {
/**
* 续写 FileOutputStream 第二个参数为true
* /r/n 换行
*/
FileOutputStream fos = new FileOutputStream("/Users/shangri-la/a.txt");
fos.write(97);
byte[] bytes = {65,66,67,68};
fos.write(bytes);
fos.write(bytes,1,2); //从哪开始,写几个
fos.write("hello\r\n".getBytes());
fos.write("word".getBytes());
fos.close();
}
}
// 写流的标准语法
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws Exception {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("/Users/shangri-la/b.txt");
fos.write(97);
} catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException("文件写入失败!请重试");
} finally {
try {
if(fos!=null)
fos.close();
} catch (IOException ex) {
System.out.println(ex.toString());
}
}
}
}
复制粘贴文件字符数组
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class copyFileDemo {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("/Users/shangri-la/c.txt");
fw = new FileWriter("/Users/shangri-la/d.txt");
char[] ch = new char[1024];
int len = 0;
while ((len = fr.read(ch)) != -1) {
fw.write(ch, 1, len);
fw.flush();
}
} catch (IOException ex) {
System.out.println(ex.toString());
} finally {
try {
if (fw != null)
fw.close();
} catch (IOException ex) {
throw new RuntimeException("释放资源失败");
} finally {
try {
if (fr != null)
fr.close();
} catch (IOException ex) {
throw new RuntimeException("释放资源失败");
}
}
}
}
}
转换流(InputStreamReader和OutputStreamWriter)
import java.io.*;
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("/Users/shangri-la/c.txt");
// 输出流的转换流
InputStreamReader fsr = new InputStreamReader(fis, "GBK");
char[] ch = new char[1024];
int len = 0;
while ((len = fsr.read(ch)) != -1) {
System.out.println(new String(ch, 0, len));
}
fsr.close();
// 缓存输入流 (提高写入速率)
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("/Users/shangri-la/c.txt"));
// 输入流的转换流
OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
osw.write("你好");
osw.close();
//-------------- 写入一个bytes数组 --------------------
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("/Users/shangri-la/d.txt"));
bos.write(90);
bos.flush();
byte[] bytes = "hello".getBytes(); // 字符串转换成byte类型并且存入一个byte数组中 new String(bytes)还原
bos.write(bytes);
bos.write(bytes, 0, 2);
bos.close();
}
}
文件复制方式【字节流】,四种方式速度大比拼
/**
* 文件复制方式,字节流,四种方式
* 1. 字节流读写单个字节 125250 毫秒
* 2. 字节流读写字节数组 193 毫秒 OK
* 3. 字节缓冲区读写单个字节。 1210 毫秒
* 4. 字节缓冲区流读写字节数组 73 毫秒 OK
*/
public class Copy {
public static void main(String[] args)throws IOException {
long s = System.currentTimeMillis();
copy_4(new File("c:\\q.exe"), new File("d:\\q.exe"));
long e = System.currentTimeMillis();
System.out.println(e-s);
}
/*
* 4. 字节缓冲区流读写字节数组
*/
public static void copy_4(File src,File desc)throws IOException{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(desc));
int len = 0 ;
byte[] bytes = new byte[1024];
while((len = bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bos.close();
bis.close();
}
/*
* 3. 字节缓冲区读写单个字节。
*/
public static void copy_3(File src,File desc)throws IOException{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(desc));
int len = 0 ;
while((len = bis.read())!=-1){
bos.write(len);
}
bos.close();
bis.close();
}
/*
* 2. 字节流读写字节数组
*/
public static void copy_2(File src,File desc)throws IOException{
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(desc);
int len = 0 ;
byte[] bytes = new byte[1024];
while((len = fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
fos.close();
fis.close();
}
/*
* 1.字节流读写单个字节
*/
public static void copy_1(File src,File desc)throws IOException{
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(desc);
int len = 0 ;
while((len = fis.read())!=-1){
fos.write(len);
}
fos.close();
fis.close();
}
}
IO流整理
打印流实现文本复制
import java.io.*;
/**
* 打印流实现文本复制
* 读取数据源 BufferedReader + FileReader 读取文本行
* 写入数据目的 PrintWriter + Println 自动刷新
*/
public class printWriteDemo {
public static void main(String[] args) throws IOException {
BufferedReader bfr = new BufferedReader(new FileReader("/Users/shangri-la/c.txt"));
PrintWriter pw = new PrintWriter(new FileWriter("/Users/shangri-la/a.txt"), true);
String line = null;
while ((line = bfr.readLine()) != null) {
pw.println(line);
}
pw.close();
bfr.close();
}
}
获取线程的名称及线程的sleep方法
1. ThreadDemo 类
package controller.Thread;
public class ThreadDemo {
/**
* 每个线程都有自己的名字
* 运行的方法main线程,名字就是main
* 其他新建的线程,默认名字都是"Thread-0"
* static Thread currentThread() 返回正在执行的线程对象
*
* 接口的另一种实现方法
* 创建Thread类,传递Runavle接口实现类
* 调用Thread类的start()方法
*/
public static void main(String[] args) throws InterruptedException {
System.out.println(new Thread().currentThread().getName());
// 第一种方法
new SleepThread().start();
// 第二种方法(接口方式Runable)
RunableDemo rd = new RunableDemo();
new Thread(rd).start();
/**
* 匿名内部类的实现程序
* new 父类的接口(){
* 重新的方法
* }
*/
new Thread() {
public void run() {
System.out.println("匿名内部类的实现");
}
}.start();
// 实现接口方式 XXX implements Runable {public void run (){}}
Runnable r = new Runnable() {
public void run() {
System.out.println("匿名接口内部类");
}
};
new Thread(r).start();
// 实现接口方式的第二种方法
new Thread(new Runnable() {
public void run() {
System.out.println("匿名接口内部类");
}
}).start();
}
}
2. SleepThread 类
package controller.Thread;
public class SleepThread extends Thread{
public void run(){
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
System.out.println(getName());
}
}
3.实现 Runnable,重写run方法
package controller.Thread;
/**
* 接口的另一种实现方法
* 实现 Runnable,重写run方法
*/
public class RunableDemo implements Runnable {
public void run() {
System.out.println("runable");
}
}
线程池的使用
package controller.Thread;
import java.util.concurrent.*;
public class ThreadPoolDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(2);
System.out.println(es);
es.submit(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + " 匿名接口内部类1");
}
});
es.submit(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + " 匿名接口内部类2");
}
});
es.submit(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + " 匿名接口内部类3");
}
});
es.shutdown();
/**
* callable接口方式实现线程
* 实现步骤
* 工厂类Executors静态方法 newFixedThreadPool方法,创建线程池对象
* submit(callabel c)
*/
ExecutorService es1 = Executors.newFixedThreadPool(2);
Future f = es1.submit(new Callable() {
public String call() throws Exception {
return "abc";
}
});
System.out.println(f.get());
es1.shutdown();
}
}
使用多线程技术,求和
// 1.MultThreadPool 类
package controller.Thread;
import java.util.concurrent.*;
/**
* 使用多线程技术,求和
* 两个线程
* 第1个是1+...+100
* 第2个是1+...+200
*/
public class MultThreadPool {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(2);
Future f1 = es.submit(new GetSumCallable(100));
Future f2 = es.submit(new GetSumCallable(200));
System.out.println(f1.get());
System.out.println(f2.get());
es.shutdown();
}
}
// 1.GetSumCallable 接口类
package controller.Thread;
import java.util.concurrent.Callable;
public class GetSumCallable implements Callable<Integer> {
private int a;
public GetSumCallable(int a) {
this.a = a;
}
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < a; i++) {
sum += i;
}
return sum;
}
}
采用同步方法形式,解决线程的安全问题
// 1. TicketDemo 类
package controller.TicketDemo;
public class TicketDemo {
public static void main(String[] args) {
Tickets tickets = new Tickets();
Thread t0 = new Thread(tickets);
Thread t1 = new Thread(tickets);
Thread t2 = new Thread(tickets);
t0.start();
t1.start();
t2.start();
}
}
// Tickets 接口
package controller.TicketDemo;
/**
* 采用同步方法形式,解决线程的安全问题
* 好处: 代码简洁
* 将线程共享数据,和同步,抽取到一个方法中
* 在方法的声明上,加入同步关键字
* 问题:
* 同步方法有锁吗,肯定有,同步方法中的对象锁,是本类对象引用 this
* 如果方法是静态的呢,同步有锁吗,绝对不是this
* 锁是本类自己.class 属性
* 静态方法,同步锁,是本类类名.class属性
*/
public class Tickets implements Runnable {
private int tickets = 100;
public void run() {
while (true) {
payTicket();
}
}
public synchronized void payTicket() {
if (tickets > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 第" + tickets-- + "张");
}
}
}
java线程中的死锁实现
//1. 创建LockA
package controller.deadLock;
public class LockA {
private LockA() {
}
public static final LockA locka = new LockA();
}
// 2.创建LockB
package controller.deadLock;
public class LockB {
private LockB() {
}
public static final LockB lockb = new LockB();
}
// 3. 利用奇偶数实现synchronized的同步锁
package controller.deadLock;
public class DeadLock implements Runnable {
private int i = 0;
public void run() {
while (true) {
if (i % 2 == 0) {
synchronized (LockA.locka) {
System.out.println(" 先进入A再进入B LockA");
synchronized (LockB.lockb) {
System.out.println(" 先进入A再进入B LockB");
}
}
} else {
synchronized (LockB.lockb) {
System.out.println(" 先进入B再进入A LockB");
synchronized (LockA.locka) {
System.out.println(" 先进入B再进入A LockA");
}
}
}
i++;
}
}
}
// 4. DeadLockDemo方法调用
package controller.deadLock;
public class DeadLockDemo {
public static void main(String[] args) {
DeadLock deadLock = new DeadLock();
Thread t1 = new Thread(deadLock);
Thread t2 = new Thread(deadLock);
t1.start();
t2.start();
}
}