700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > java基础 —— 集合 异常 反射 io流 多线程

java基础 —— 集合 异常 反射 io流 多线程

时间:2021-05-14 21:01:46

相关推荐

java基础 —— 集合 异常 反射 io流 多线程

1.集合 (Collection)

list接口:储存有序可重复数据。

在使用list储存数据时,如果储存的是对象,那么对象多对应的类要重写equals()方法。

Arraylist:作为list接口的主要实现类;线程不安全,高效率;可以存储null值Linkedlist:对于频繁的插入、删除操作,使用此类效率比Arraylist 高;底层使用双链表储存;可以储存null值Vector:作为list古老实现类;线程安全,效率低;底层使用Object[] elementData储存。

set接口:储存无序不可重复数据

在使用hashSet 、LinkedhashSet 储存数据时,如果储存的是对象,那么对象多对应的类要重写equals()方法 和 hashcode()方法。

hashSet:作为set主要实现类; 线程不安全;可以储存null值

底层原理:在添加元素的时候,HashSet会先调用元素的hashcode方法得到元素的哈希值 ,然后通过元素的哈希值经过移位等运算,就可以算出该元素在哈希表中的存储位置

1、如果算出的元素存储的位置目前没有任何元素存储,那么该元素可以直接存储在该位置上。

2、如果算出的元素的存储位置目前已经存在有其他的元素了,那么还会调用该元素的equals方法

与该位置的元素再比较一次,如果equals方法返回的是true,那么该位置上的元素视为重复元

素,不允许添加,如果返回的是false,则允许添加。

LinkedhashSet:LinkedhashSet 是 hashSet的子类; 对于频繁的遍历操作,linkedhashSet效率高于hashSet。

TreeSet:可按照添加对象的指定属性进行排序;不可储存null值;

Collection使用迭代器遍历集合数据

Collection<String> collection = new ArrayList<String>();collection.add("1223");Iterator<String> iterator = collection.iterator();while (iterator.hasNext()) {Object object = iterator.next();System.out.println(object.toString());}

Collection使用foreach遍历集合数据

Collection<String> collection = new ArrayList<String>();collection.add("1223");for (String string : collection) {System.out.println(string);}

collection接口常用方法

添加、删除、修改操作:

Object add(Object obj):添加数据。

Object remove(Object obj):移除对应数据。

void clear():清空集合中所有数据。元素查询操作

boolean contains(Object obj):判断元素是否存在。

int size():返回集合中元素的个数。

boolean isEmpty():判断当前集合是否为空。

retainAll(Collection c) //保留两个集合的交集

参考:/iruier_/article/details/80010308

Map:映射关系集合,以key—value形式储存数据;其中的 key 是无序不可重复的

在HashMap中如果key是自定义的类,类中就要重写equals()方法和 hashcode()方法。

hashMap:

作为Map的主要实现类,线程不安全,效率高;key可以为null,当key为null是会返回0; 源码如下:

hashMap在put时会调用 hash()方法来计算key的hashcode值,可以从hash算法中看出当 key为null时返回的值是0。因此key为null时,hash算法返回值为0,不会调用key的hashcode()方法。

LinkedHashMap:

保证在遍历Map元素时,可以按照添加顺序实现遍历。在原有的HashMap底层结构基础上添加了一对指针,指向前一个和后一个元素,对应频繁的遍历操作,执行效率高于HashMap

TreeMap:

保证按照添加的key-value对进行排序,实现排序遍历。

Hashtable:线程安全的,效率低;储存的key不能为null。

Map接口的常用方法

添加、删除、修改操作:

Object put(Object key,Object value):添加key - value 类型数据。

void putAll(Map m):将m中所有数据存放到map中。

Object remove(Object key):移除key所对应的value的值。

void clear():清空map中所有数据。元素查询操作

Object get(Object key):获取key所对应的value的值。

boolean containsKey(Object key):判断key是否存在。

boolean containsValue(Object value):判断value值是否存在。

int size():返回map中key—value对 的个数。

boolean isEmpty():判断当前map是否为空。

boolean equals(Object obj):判断当前map和参数对象obj是否相等。

使用Collections工具类是用来操作collection接口

1.void copy(List dest , List src):将src中的类容复制到dest中。 例如:

List list = new ArrayList();list.add("abc");System.out.println(list);List nlist = Arrays.asList(new Object[list.size()]);//将list中的类容复制到 nlist中Collections.copy(nlist, list);System.out.println(nlist);

2.使用Collections.synchronizedXXX(XXX) 可以解决多线程并发访问时的线程安全问题。例如

//dlist 线程不安全List dList = new ArrayList();//nlist 为线程安全的List nlList = Collections.synchronizedList(dList);

2.异常

捕获异常:使用 try…catch 语句,try中是有可能出现异常的代码,catch中使用 e.printStackTrace()方法打印异常信息;try…catch语句是在方法中使用

声明异常:使用 throws ,跟在方法的后面,可以接多个异常类

自定义异常

创建类继承Exception类或者Exception的子类重写构造方法

public class MyServiceException extends RuntimeException {private static final long serialVersionUID = 1L;private String code;private String msg;public MyServiceException(ResponseEnum e){super(e.getMsg());this.code = e.getCode();this.msg = e.getMsg();}public MyServiceException(String code, String msg) {super(msg);this.code = code;this.msg = msg;}}

手动抛出异常

找到一个合适的在这里插入代码片异常类创建这个异常类的对象抛出这个对象

public void orderTask(){//使用throw手动抛出异常 (MySericeExcption是自定义异常)throw new MyServiceException("11","fff"); }

参考视频/video/BV1nC4y1s7EY?from=search&seid=4430483164806649866

3.反射

1、什么是反射

反射:是Java被视为动态语言的关键;反射机制允许程序在运行期间,借助反射API获取任何类的全部信息,并且能够直接操作这些类的属性和方法。

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。

2、获取Class类的实例(三种方式)

通过类直接获取

Class c3 = Student.class;

通过类的一个实例,调用getClass()方法获取

People people = new Student(); Class c1 = people.getClass();

通过类的全路径获取(包名+类名)

Class c2 = Class.forName("ThreeClass.Student");

3、Class类的常用方法

4、反射获取类的属性、方法和构造器

1. 获取类的属性

Class people = Class.forName("People");Class user = Class.forName("user");/** 1、获取类的属性*///获取当前类和父类的所有public属性Field[] fields = people.getFields();for (Field field : fields) {System.out.println(field);}//获取当前类的所以public和private属性Field[] f2 = user.getDeclaredFields();for (Field field : f2) {System.out.println("Field暴力获取"+field);}//获取指定属性Field name = user.getField("name"); //获取public属性System.out.println(name);Field age = user.getDeclaredField("age"); //获取私有的属性System.out.println(age);

2. 获取类的方法

/** 2、获取类的方法*///获取当前类和父类的所有public方法Method[] m1 = user.getMethods();for (Method method : m1) {System.out.println(method);}//获取当前类所有的public和private方法Method[] m2 = user.getDeclaredMethods();for (Method method : m2) {System.out.println("暴力获取"+method);}//获取指定的方法Method test = user.getMethod("test"); //获取public方法System.out.println("获取public方法"+test);Method ptest = user.getDeclaredMethod("ptest"); //获取privata方法System.out.println("获取private方法"+ptest);

3. 获取类构造器

/** 3、获取构造器*///获取当前类public构造器Constructor[] c1 = people.getConstructors();for (Constructor constructor : c1) {System.out.println(constructor);}//获取当前类public和private构造器Constructor<?>[] c2 = people.getDeclaredConstructors();for (Constructor<?> constructor : c2) {System.out.println("暴力获取"+constructor);}//获取指定的构造器Constructor c3 = user.getConstructor(String.class, Integer.class);System.out.println("指定public构造器"+c3);Constructor c4 = user.getDeclaredConstructor(null);System.out.println("获取指定的private"+c4);

5、反射操作类的属性、方法

1. 反射创建对象

Class user = Class.forName("user");Class people = Class.forName("People");/** 1、通过反射创建对象*///默认调用的无参构造user u1 = (user) user.newInstance();System.out.println(u1);//使用有参构造Constructor<?> constructor = user.getDeclaredConstructor(String.class, Integer.class);user ul2 = (user) constructor.newInstance("小婉", 17);System.out.println(ul2);

2. 反射执行方法

/**2、通过反射执行方法* invoke(实例化的对象,方法中的参数)*/Method m1 = user.getDeclaredMethod("test");m1.invoke(u1);Method m2 = user.getDeclaredMethod("ptest");m2.setAccessible(true); //ptest()方法为private的 ,要关闭安全检查才能执行m2.invoke(u1);

3. 反射操作属性

/** 3、通过放射操作属性* set(实例化的对象,属性值)*/Field f1 = people.getDeclaredField("pname");People peo = (People) people.newInstance();f1.setAccessible(true); //pname方法为private的 ,要关闭安全检查设置值f1.set(peo,"小红");System.out.println(peo.getPname());

注意点:

操作私有属性和方法时,要关闭安全权限检查,设置setAccessible(true),否则执行不了。

4.io流

1、File类

1.1、file类的三种构造方法

File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。

File f1 = new File("D:/下载/JavaSE.png");

File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例。

File f2 = new File("D:/","下载/JavaSE.png");

File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例

File file = new File("D:/");File f3 = new File(file,"下载/JavaSE.png");

1.2、file类的常用方法

获取功能的方法

public String getAbsolutepath(); 获取绝对路径名字符串public String getpath(); 获取相对路径字符串public String getName(); 获取文件名或文件夹名public long length(); 文件大小的字节长度 ( 文件夹没有大小为 0 )public long lastModified(); 获取最后一次的修改时间

File file = new File("a.txt");System.out.println(file.getPath()); //获取相对路径System.out.println(file.getAbsolutePath()); //获取绝对路径System.out.println(file.getName()); //获取文件名或文件夹名System.out.println(file.length()); //获取文件大小的字节长度(文件夹没有大小默认是0)long l1 = file.lastModified(); //获取最后修改的时间Date date = new Date(l1);String format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);System.out.println(format1);

运行结果:

判断功能的方法

public boolean isDirectory(); 判断是否是目录public boolean isFile(); 判断是否是文件public boolean exists(); 判断是否存在public boolean canRead(); 判断是否可读public boolean canwrite(); 判断是否可写public boolean isHidden(); 判断是否隐藏

创建删除功能的方法

public boolean createNewFile(); 当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。public boolean mkdir(); 创建由此抽象路径名命名的目录。public boolean mkdirs(); 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录public boolean delete(); 删除由此抽象路径名表示的文件或目录。

遍历文件夹目录

String[] list() 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。File[] listFiles() 返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件。

//list遍历返回的是字符数组File file = new File("D:/下载");String[] list = file.list();for (String s : list) {System.out.println(s);

没有遍历文件夹的文件,遍历不完全

//listfiles遍历返回的是字符数组public static void getAllfile(String string){File file = new File(string);File[] files = file.listFiles();for (File file1 : files) {if (file1.isDirectory()){getAllfile(file1.getPath());}else {System.out.println(file1); //默认调用的是getputh}}}

遍历结果:全部遍历了

例题:遍历D:/下载 下的所有.java文件

第一种

File file = new File(string);File[] files = file.listFiles();for (File file1 : files) {if (file1.isDirectory()){getAllfile(file1.getPath());}else {if (file1.getPath().endsWith(".java")){System.out.println(file1);}}}

遍历结果:

第二种:实现过滤器

public static void getAlltofilter(String string){File file = new File(string);File[] files = file.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {if (pathname.isDirectory()){return true;}else if(pathname.getPath().endsWith(".java")){return true;}else {return false;}}});for (File file1 : files) {if (file1.isDirectory()){getAlltofilter(file1.getPath());}else {System.out.println(file1);}}}

遍历结果:

2、IO流

2.1、字节流

一切文件数据(文本、图片、视频等)都是以二进制的形式保存

字节输入流和输出流

OutputStream和InputStream是抽象类,其具体实现要看其子类

InputStream常用方法:

abstract int read() 从输入流读取数据的下一个字节。void close() 关闭此输入流并释放与流相关联的任何系统资源。int read(byte[] b) 从输入流读取一些字节数,并将它们存储到缓冲区 b 。int read(byte[] b, int off, int len) 从输入流读取最多 len字节的数据到一个字节数组。

OutputStream常用方法:

void close() 关闭此输出流并释放与此流相关联的任何系统资源。void flush() 刷新此输出流并强制任何缓冲的输出字节被写出。void write(byte[] b) 将 b.length字节从指定的字节数组写入此输出流。void write(byte[] b, int off, int len) 从指定的字节数组写入 len个字节,从偏移 off开始输出到此输出流。abstract void write(int b) 将指定的字节写入此输出流。

1、FileInputStream和FileOutputStream 文件操作流

FileInputStream

构造方法:

FileInputStream(File file) ; 通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。FileInputStream(String name) ; 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。

FileOutputStream

构造方法:

FileOutputStream(File file) ; 创建文件输出流以写入由指定的 File对象表示的文件。FileOutputStream(String name) ;创建文件输出流以指定的名称写入文件。FileOutputStream(File file, boolean append) ;创建文件输出流以写入由指定的 File对象表示的文件,append设置为true 可追加写。FileOutputStream(String name, boolean append) ;创建文件输出流以指定的名称写入文件,append设置为true 可追加写。

测试代码:

//1.FileInputStream 读取 a.txt 文件FileInputStream f1 = new FileInputStream("a.txt");FileOutputStream f2 = new FileOutputStream("b.txt", true);byte[] bytes= new byte[1024];int len;while ((len =(f1.read(bytes)))!= -1){System.out.println(new String(bytes,0,len));//2.FileOutputStream 向b.txt 中写入数据//append :true 表示不会覆盖文件数据,可以继续向文件中写入数据f2.write(bytes,0,len);}//3.关闭流资源f1.close();f2.close();

2、ObjectInputStream和ObjectOutputStream 序列化流

ObjectOutputStream 序列化

构造方法:

ObjectOutputStream(OutputStream out)

创建一个写入指定的OutputStream的ObjectOutputStream。

特有方法:

void writeObject(Object obj) 将指定的对象写入ObjectOutputStream。

ObjectInputStream 反序列化

构造方法:

ObjecInputStream(InputStream in)

创建一个写入指定的InputStream的ObjectInputStream。

特有方法:

void readObject(Object obj) 将指定的对象写入ObjectInputStream。

实例代码:

User user = new User("小王",12);//1、将对象序列化储存到 c.txt 文件中ObjectOutputStream o1 = new ObjectOutputStream(new FileOutputStream("c.txt"));o1.writeObject(user);o1.close();//2、将 c.txt 文件中存储的对象反序列化,得到对象ObjectInputStream o2 = new ObjectInputStream(new FileInputStream("c.txt"));User o = (User)o2.readObject();System.out.println(o);

注意点:

1、序列化的对象,其实体类要实现 Serializable 接口

2、当某个属性不想被序列化时,可以用 transient 修饰

2.2、字符流

字符输入流和输出流

Reader 和 Writer 是抽象类,其具体实现要看其子类

Reader常用方法:

abstract void close() 关闭流并释放与之相关联的任何系统资源。int read() 读一个字符int read(char[] cbuf) ; 将字符读入数组read(char[] cbuf, int off, int len) ; 将字符读入数组的一部分。read(CharBuffer target) ; 尝试将字符读入指定的字符缓冲区。

Writer常用方法:

abstract void close() ; 关闭流,先刷新。abstract void flush() ; 刷新流。void write(char[] cbuf) ; 写入一个字符数组。abstract void write(char[] cbuf, int off, int len) ; 写入字符数组的一部分。void write(String str) ; 写一个字符串void write(String str, int off, int len) ; 写一个字符串的一部分。

1、InputStreamReader和OutputStreamWriter 转换流

InputStreamReader

构造方法:

InputStreamReader(InputStream in) ;创建一个使用默认字符集的InputStreamReader。InputStreamReader(InputStream in, String charsetName) ; 创建一个使用命名字符集的InputStreamReader。

OutputStreamWriter

构造方法:

OutputStreamWriter(OutputStream out) ; 创建一个使用默认字符编码的OutputStreamWriter。OutputStreamWriter(OutputStream out, Charset cs) ; 创建一个使用给定字符集的OutputStreamWriter。

public static void main(String[] args) throws Exception {InputStreamReader ir1 = new InputStreamReader(new FileInputStream("b.txt"),"UTF-8");//charsetName 设置文件编码格式 append:true 设置可追加写入OutputStreamWriter or1 = new OutputStreamWriter(new FileOutputStream("d.txt",true),"GBK");//1、InputStreamReader读取b.txt 文件int len = 0;char[] chars = new char[1024];while ((len = (ir1.read(chars))) != -1){String s = new String(chars, 0, len);System.out.println(s);//2、OutputStreamWriter 将读取到的b.txt 文件的内容,写入到d.txtor1.write(s);}//3、关闭资源or1.close();ir1.close();}

控制台输出:

b.txt 文件

d.txt 文件

2.3、缓冲流

1、BufferedInputStream和 BufferedOutputStream 字节缓冲流

BufferedInputStream构造方法:

BufferedInputStream(InputStream in) ; 创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。BufferedInputStream(InputStream in, int size) ; 创建 BufferedInputStream具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。

测试代码:

BufferedInputStream b1 = new BufferedInputStream(new FileInputStream("a.txt"));int len = 0;byte[] bytes = new byte[1024];while ((len=(b1.read(bytes))) != -1){String s = new String(bytes, 0, len);System.out.println(s);}b1.close();

BufferedOutputStream构造方法:

BufferedOutputStream(OutputStream out) ; 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。BufferedOutputStream(OutputStream out, int size) ; 创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。

测试代码:

public static void main(String[] args) throws Exception {BufferedOutputStream b1 = new BufferedOutputStream(new FileOutputStream("a.txt", true));b1.write("妖精的尾巴".getBytes());b1.flush();b1.close();}

2、BufferedReader和BufferedWriter 字符缓冲流

BufferReader构造方法:

BufferedReader(Reader in) ;创建使用默认大小的输入缓冲区的缓冲字符输入流。BufferedReader(Reader in, int sz) ;创建使用指定大小的输入缓冲区的缓冲字符输入流。

特有方法:

String readLine() 读一行文字,读取到末尾,返回值不是-1 而是 null。

测试代码:

BufferedReader b1 = new BufferedReader(new FileReader("a.txt"));String len;while ((len = b1.readLine()) != null){System.out.println(len);}b1.close();

结果:

BufferedWriter构造方法:

BufferedWriter(Writer out) ; 创建使用默认大小的输出缓冲区的缓冲字符输出流。BufferedWriter(Writer out, int sz) ; 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。

特有方法:

newLine() 写入一个行分隔符

测试代码:

BufferedWriter b1 = new BufferedWriter(new FileWriter("a.txt", true));b1.newLine(); //换行b1.write("风吹云雾见真容");b1.flush();b1.close();

结果:

学习视频:/video/BV1Y4411P7Ey

参考视频:/video/BV1v5411W7ZE

5.多线程

1、创建线程的三种方式

继承Thread类

//线程实现方式一public class ThreadDome01 extends Thread{@Overridepublic void run() {for (int i=0;i<20;i++){System.out.println("看小说"+i);}}public static void main(String[] args) {//开启ThreadDome01线程new ThreadDome01().start();for (int i=0;i<2000;i++){System.out.println("主线程执行"+i);}}}

实现Runnable接口

public class RunnableDome01 implements Runnable{@Overridepublic void run() {for(int i = 0;i<20;i++){System.out.println("runnable实现线程"+i);}}public static void main(String[] args) {//开启实现Runnable接口的线程RunnableDome01 dome01 = new RunnableDome01();new Thread(dome01).start();for (int i = 0;i<200;i++){System.out.println("main线程"+i);}}}

实现Callable接口

例1:

public class CallableDome01 implements Callable<Boolean> {@Overridepublic Boolean call(){for(int i = 0;i<20;i++){System.out.println("runnable实现线程"+i);}}public static void main(String[] args) throws ExecutionException, InterruptedException {CallableDome01 t1 = new CallableDome01();//1、开启服务ExecutorService executor = Executors.newFixedThreadPool(3); //3为开启线程个数//2、开启线程Future<Boolean> f1 = executor.submit(t1);//3、获取返回值Boolean aBo1 = f1.get();//4、关闭服务executor.shutdown();}}

例2:

public class CallableDome02 {public static void main(String[] args) {FutureTask futureTask = new FutureTask(new MyThread());new Thread(futureTask).start();try {Integer integer = (Integer) futureTask.get();System.out.println(integer);} catch (Exception e) {e.printStackTrace();}}}class MyThread implements Callable{@Overridepublic Integer call() throws Exception {return 100;}}

2、线程方法和状态

sleep() 线程休眠

线程休眠,不会释放锁,会阻塞

yield() 礼让方法

对于同一个对象,开启的两个线程,进入cup中的线程调用yield()方法,会改变线程为就绪状态, 下一次两个线程谁先执行看cup心情

setpriority() 设置线程的优先级

优先级默认是5,权重大的优先执行

join() 线程插队

可以使插队的线程优先主线程执行

setDaemon(true) 设置线程为守护线程

Thread thread = new Thread(dome02);

thread.setDaemon(true);

3、线程同步

3.1、线程同步中死锁问题

什么是死锁:多个线程持有对方的资源,形成僵持产生死锁的四个条件:

1、互斥条件:一个资源每次只能被一个线程访问

2、请求与保持条件:一个进程因请求资源而阻塞式,对以获得的资源保持不放

3、不剥夺条件:进程获得的资源,在未使用完成之前,不能被强行剥夺

4、循环等待条件 :若干个进程之间形成一种头尾相接的循环等待资源关系

线程死锁代码:

public class DeadLock {public static void main(String[] args) {new Thread(new TestThread(1)).start();new Thread(new TestThread(0)).start();}}class A{}class B{}class TestThread implements Runnable{static A a = new A();static B b = new B();private int flag;public TestThread(int flag){this.flag = flag;}@Overridepublic void run() {if (flag == 1){synchronized (a){System.out.println(Thread.currentThread().getName()+"获取的 a 对象的锁");try {Thread.sleep(1000); //模拟延迟,不让1一下拿到两个对象的锁} catch (InterruptedException e) {e.printStackTrace();}//1、死锁/*synchronized (b){System.out.println(Thread.currentThread().getName()+"获取的 b 对象的锁");}*/}//2、解决死锁的方法synchronized (b){System.out.println(Thread.currentThread().getName()+"获取的 b 对象的锁");}}else if (flag == 0){synchronized (b){System.out.println(Thread.currentThread().getName()+"获取的 b 对象的锁");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//1、死锁/*synchronized (a){System.out.println(Thread.currentThread().getName()+"获取的 a 对象的锁");}*/}//2、解决死锁synchronized (a){System.out.println(Thread.currentThread().getName()+"获取的 a 对象的锁");}}}}

3.2、实现线程同步

synchronized 同步代码块

synchronized 锁的是对象,一般是公共资源,可用于方法。

//使用同步代码块来解决Arraylist线程不安全问题public class ListTest {public static void main(String[] args) {//arraylist是线程不安全的List<String> list = new ArrayList<>();synchronized (list){for (int i = 0; i < 1000; i++) {new Thread(()->{list.add(Thread.currentThread().getName());}).start();}}try {Thread.sleep(8000);System.out.println(Thread.currentThread().getName());}catch (Exception e){e.printStackTrace();}System.out.println(list.size());}}

lock锁

Reentrantlock 可重入所

public class LockDome {public static void main(String[] args) {Test01 test01 = new Test01();new Thread(test01).start();new Thread(test01).start();new Thread(test01).start();}}class Test01 implements Runnable{private int i = 10;private final ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {while (true){try {lock.lock();if (i>0){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"拿到了第"+i--+"票");}else {break;}}finally {lock.unlock();}}}}

4、线程通信

通过缓冲区(管程法)

/*** 测试生产者和消费者模型—> 利用缓冲区解决:管程法* 生产者、消费者、产品、缓存区*/public class TestPC {public static void main(String[] args) {SynContainer container = new SynContainer();new Thread(new Productor(container)).start();new Thread(new Consumer(container)).start();}}//生产者class Productor implements Runnable{SynContainer container;Productor(SynContainer container){this.container = container;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {container.push(new Chicken(i));System.out.println("生产了第"+i+"只鸡");}}}//消费者class Consumer implements Runnable{SynContainer container;Consumer(SynContainer container){this.container = container;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {container.pop(new Chicken(i));System.out.println("消费了第"+i+"只鸡");}}}//产品class Chicken{private int id; //编号Chicken(int id){this.id = id;}}//缓存区class SynContainer{//设置容器大小Chicken[] chickens = new Chicken[10];//容器计数器int conut = 0;//生产者生产放入产品public synchronized void push(Chicken chicken){if (conut == chickens.length){//通知消费者消费try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}chickens[conut] = chicken;conut++;//通知消费者消费this.notifyAll();}//消费者消费取出产品public synchronized Chicken pop(Chicken chicken){if (conut == 0){//通知生产者生产try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}conut--;Chicken chicken1= chickens[conut];//吃完通知生产者生产this.notifyAll();return chicken1;}}

5、线程池

public class ThreadPool {public static void main(String[] args) throws ExecutionException, InterruptedException {//1、创建线程池 newFixedThreadPool 参数为池子大小ExecutorService service = Executors.newFixedThreadPool(5);//2、执行线程service.submit(new MyThread01());service.submit(new MyThread01());service.execute(new MyThread01());Future submit = service.submit(new MyThread02());Integer number = (Integer) submit.get();System.out.println(number);//3、关闭线程池service.shutdown();}}class MyThread01 implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"MyThread01");}}class MyThread02 implements Callable {@Overridepublic Integer call() throws Exception {System.out.println(Thread.currentThread().getName()+"MyThread02");return 11;}}

注意点:

线程池submit()方法 既可以执行Runnable接口 线程,也可执行 Callable 接口线程;线程池execute()方法只能执行 Runnable接口 线程

视屏:/video/BV1V4411p7EF?p=27

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。