线程安全问题
public class TestSafy {
private static String[] arr=new String[5];
private static int index=0;
public static void main(String[] args) throws Exception {
//创建一个任务放入hello
Runnable tast01=new Runnable() { //匿名内部类
@Override
public void run() {
if(arr[index]==null){ //时间到了
arr[index]="hello";
index++;
}
}
};
Runnable tast02=new Runnable() { //匿名内部类
@Override
public void run() {
if(arr[index]==null){
arr[index]="world";//时间到了
index++;
}
}
};
Thread t1=new Thread(tast01,"线程A");
Thread t2=new Thread(tast02,"线程B");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(Arrays.toString(arr)); //属于main
}
}
解决线程安全问题----加锁
(1)synchronized----自动锁
public class TestSafy {
private static String[] arr=new String[5];
private static int index=0;
public static void main(String[] args) throws Exception {
//创建一个任务放入hello
Runnable tast01=new Runnable() { //匿名内部类
@Override
public void run() {
synchronized (arr) { //()锁资源-----共享资源作为锁资源.只要使用的是同一把锁资源就可以上锁成功。
if (arr[index] == null) { //时间到了
arr[index] = "hello";
index++;
}
}
}
};
Runnable tast02=new Runnable() { //匿名内部类
@Override
public void run() {
synchronized (arr) {
if (arr[index] == null) {
arr[index] = "world";//时间到了
index++;
}
}
}
};
Thread t1=new Thread(tast01,"线程A");
Thread t2=new Thread(tast02,"线程B");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(Arrays.toString(arr)); //属于main
}
}
public class TestTicket {
public static void main(String[] args) {
Ticket task=new Ticket();//任务对象
Thread t1=new Thread(task,"窗口A");
Thread t2=new Thread(task,"窗口B");
Thread t3=new Thread(task,"窗口C");
Thread t4=new Thread(task,"窗口D");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Ticket implements Runnable {
private Integer ticket = 100;
private Object o=new Object(); //新建一个Object做为锁资源
@Override
public void run() {
while (true) {
synchronized (this) { //()要的是一个对象! tiket它是一个int类型
if (ticket <= 0) {
break;
}
ticket--;
System.out.println(Thread.currentThread().getName() + "卖了一张,剩余:" + ticket + "张");
}
}
}
}
(2)lock------手动锁。
public class TestSafy {
private static String[] arr=new String[5];
private static int index=0;
public static void main(String[] args) throws Exception {
final Lock lock=new ReentrantLock();//重入锁:可以多次加锁。 创建一个手动锁对象
//创建一个任务放入hello
Runnable tast01=new Runnable() { //匿名内部类
@Override
public void run() {
try {
lock.lock();//上锁
if (arr[index] == null) { //时间到了
arr[index] = "hello";
index++;
}
}finally { //finally有没有异常都会执行
lock.unlock();//解锁
}
}
};
Runnable tast02=new Runnable() { //匿名内部类
@Override
public void run() {
try {
lock.lock();
if (arr[index] == null) {
arr[index] = "world";//时间到了
index++;
}
}finally {
lock.unlock();
}
}
};
Thread t1=new Thread(tast01,"线程A");
Thread t2=new Thread(tast02,"线程B");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(Arrays.toString(arr)); //属于main
}
}
public class TestTicket {
public static void main(String[] args) {
Ticket task=new Ticket();//任务对象
Thread t1=new Thread(task,"窗口A");
Thread t2=new Thread(task,"窗口B");
Thread t3=new Thread(task,"窗口C");
Thread t4=new Thread(task,"窗口D");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Ticket implements Runnable {
private Lock lock=new ReentrantLock();
private Integer ticket = 100;
private Object o=new Object(); //新建一个Object做为锁资源
@Override
public void run() {
while (true) {
try{
lock.lock();
if (ticket <= 0) {
break;
}
ticket--;
System.out.println(Thread.currentThread().getName() + "卖了一张,剩余:" + ticket + "张");
}finally {
lock.unlock();
}
}
}
}
HashMap和HashTable的区别?
HashMap:允许key和value为null,hashmap线程不安全,但是效率高。
HashTable:不允许key和value为null,它线程安全,效率低。
HashMap的底层如何实现?
1、 数组+链表+红黑二叉树。 hashMap存放调用的是put(key,value),根据key的hash值进行判断是否有相同哈希值的元素在数组中,如果没有则存入数组中,如果存在相同哈希值的元素,则认为哈希冲突,则比较他们的equals是否相同,如果相同,则认为是同一个元素,则替换原来key对应的value值。 如果不同,则存入链表,如果哈希冲突的元素过多(8),则存入红黑二叉树。
ArrayList和LinkedList的区别!
1. ArrayList:底层是数组结构,是一块连续的内存空间,适合查询操作,不是插入和删除操作,因为插入和删除,牵涉到数据的迁移。
2. LinkedList:底层是链表结构,适合插入和插入操作,不适合查找操作。
String,StringBuffer和StringBuilder的区别
1. String底层使用final修饰。其值不可改变,每次改变重新生成引用地址。
2. StringBuffer和StringBuilder其值可以改变,使用append进行追加。
3. StringBuffer线程安全,但是效率低,建议多线程下使用。
4. StringBuilder线程不安全,但是效率高,建议单线程下使用。
死锁以及如何避免死锁。
十秒后自动解锁