Java 容器常用方法
Java容器线程安全及不安全
Map
1.插入
Map<String, String> map = new HashMap<String, String>();
map.put("id", "张三");
map.put("username", "张三");
map.put("password", "123123");
2.删除
只通过key删除返回String (返回的是删除key的value)
map.remove("id");
通过key value删除返回boolean
3.遍历
1.在for-each循环中使用entry来遍历
for (Map.Entry<String, String> entry : map2.entrySet()) { System.out.print("key:"+entry.getKey()); System.out.println("value:"+entry.getValue()); }
2. 在for-each循环中遍历keys或values。
for (String keys : map2.keySet()) {
System.out.println("keys="+keys);
}
for(String keys : map2.values()) {
System.out.println("value="+keys);
}
3.泛型遍历
Iterator<Map.Entry<String, String>> entry = map.entrySet().iterator();
while(entry.hasNext()) {
Map.Entry<String, String> entry1 = entry.next();
System.out.println("Key = " + entry1.getKey() + ", Value = " + entry1.getValue());
}
List
1.插入
add();实现
2.删除
list.remove(index)通过下表删除返回Object
boolean bool = list.remove(“add插入”);通过value返回boolean
3.遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
Set
1.插入
Set<String> set = new HashSet<String>();
set.add("set插入1");
2.删除
set.remove("set插入1");
3.遍历
for (String string : set) {
System.out.println(string);
}
实现多线程的方式
1.继承Thread类
2.实现Runnable接口
3.通过Callable和Future创建线程
线程操作方法
1、线程睡眠—sleep
线程睡眠的原因:线程执行的太快,或需要强制执行到下一个线程。
线程睡眠的方法(两个):sleep(long millis)在指定的毫秒数内让正在执行的线程休眠。
sleep(long millis,int nanos)在指定的毫秒数加指定的纳秒数内
让正在执行的线程休眠。
2、线程让步—yield
该方法和sleep方法类似,也是Thread类提供的一个静态方法,可以让正在执行的线程暂停,但是不会进入阻塞状态,而是直接进入就绪状态。相当于只是将当前线程暂停一下,然后重新进入就绪的线程池中,让线程调度器重新调度一次。也会出现某个线程调用yield方法后暂停,但之后调度器又将其调度出来重新进入到运行状态。
3、线程合并—join
当B线程执行到了A线程的.join()方法时,B线程就会等待,等A线程都执行完毕,B线程才会执行。
4.各类线程是否安全
以ArrayList和Vector为例, 同时建立100个线程, 每个线程都向容器中添加100个元素,
最后统计容器内元素的数量, 对于ArrayList来说, 最后的量并不一定是10000个, 甚至会出现IndexOutofBoundsException, 但是对于Vector来说, 最后的量一定是10000个, 且不会出现任何异常. 这便是线程安全与非线程安全的一个直观表现.
5.如何使非线程安全容器类变得线程安全
使用List list = Collections.synchronizedList(new ArrayList());可以使list变得线程安全.
6.造成非线程安全的原因
一般来说, 造成非线程安全主要有两个原因:
- 一个操作不是原子性操作
- 执行过程中可能被中断
7.Java中给我们提供是同步代码块技术来解决这个线程的安全问题:
synchronized(任意的对象(锁) )
{
写要被同步的代码
}
8.同步代码块就可以认为成卫生间的门和锁。
同步函数:就是用synchronize关键字修饰的方法。因为每个java对象都有一个内置锁,当用 synchronize关键字修饰方法时内置锁会保护整个方法,而在调用该方法之前,要先获得内置锁,否则就会处于阻塞状态。
多线程安全问题,是由于多个线程在访问共享的数据(共享的资源),并且操作共享数据的语句不止一条。那么这样在多条操作共享数据的之间线程就可能发生切换。只要切换就有安全问题,那么我们就可以把同步加在这些操作共享数据的代码上。
9.单例懒汉式线程并发问题
单例设计模式:保证当前程序中的这个类对象唯一。
单例设计模式代码书写步骤:
1、私有本类的构造方法
2、创建本类对象
3、对外提供访问本类对象的方法
//饿汉式
class Single
{
private Single(){}
private static final Single s = new Single();
public static Single getInstance()
{
return s;
}
}
//懒汉式
class Single
{
private Single(){}
private static Single s = null;
public static Single getInstance()
{
if( s == null )
{
s = new Single();
}
return s;
}
}
10、死锁
进程A中包含资源A,进程B中包含资源B,A的下一步需要资源B,B的下一步需要资源A,所以它们就互相等待对方占有的资源释放,所以也就产生了一个循环等待死锁。
死锁形成的必要条件总结(都满足之后就会产生):
①、互斥条件:资源不能被共享,只能被同一个进程使用;
②、请求与保持条件:已经得到资源的进程可以申请新的资源;
③、非剥夺条件:已经分配的资源不能从相应的进程中强制剥夺;
④、循环等待条件:系统中若干进程形成环路,该环路中每个进程都在等待相邻进程占用的资源。
线程池作用
起因: 有没有一种办法使得线程可以复用,从而避免线程的频繁创建?也就是说,当线程执行完一个任务时,并不被销毁,而是可以继续执行其他的任务?
解决:在Java中,我们可以通过线程池来达到线程复用的效果