java基础学习
java 泛型
<?> 无边界
类与接口
代码块
两种代码块
{}非静态
// 会在new的时候自动加载 // 作用: 可以在创建对象时对属性赋值
static{}静态
// 静态属性和静态方法会随着类的加载而加载 // 代码块中的代码会自动执行 // 作用:相当于构造器
final
修饰类 没有子类
java反射机制
进程与线程
线程的创建和使用
-
继承使用
- 类继承Thread
- 重写run方法
- start()
class Mythread extends Thread{ @Override public void run() { // TODO 运行 for (int j = 0; j < 10; j++) { System.out.println(j); } } } // mian.java Mythread mythread = new Mythread(); mythread.start();
线程的生命周期
五种状态
- 新建
当一个Thread类或其子类被声明和创建时
- 就绪
被start()后,进入线程队列等待cpu的时间片
- 运行
当线程被调度并获得cpu资源时,进入运行状态
- 阻塞
人为挂起或执行输入输出时,临时中止操作
- 死亡
执行结束,出现异常,人为停止
解决线程不安全的问题
实现的解决
- 方法一:同步代码块
说明:
同步的代码就是操作共享数据的代码
同步监视器就是锁
多个线程必须共用一把锁
syncchronized(同步监视器){ // 需要同步的代码 }
class window1 implements Runnable { private int ticket = 100; Object oj = new Object(); @Override public void run() { while (true) { synchronized (oj) { if (ticket > 0) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } ticket--; System.out.println(Thread.currentThread().getName() +"------"+ ticket); } else { break; } } } } }
- 方法二:同步方法
解决了线程安全的问题
但是在同步代码块只能有一个线程在执行.相当是一个单线程的过程,效率低
class window1 implements Runnable { private int ticket = 100; Object oj = new Object(); @Override public void run() { while (true) { if (!show()) { break; } } } // 把要同步的代码块抽出来 private synchronized boolean show() { // 用的锁是this if (ticket > 0) { try { Thread.sleep(100); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } ticket--; System.out.println(Thread.currentThread().getName() + "------" + ticket); return true; } else { return false; } } }
- 方法三:Lock ----JDK5.0新增
class window1 extends Thread { private static int ticket = 100; // 是否是公平锁 private static ReentrantLock lock = new ReentrantLock(true); // 使用懒汉模式 // private static Object oj = new Object();
@Override
public void run() {
while (true) {
try {
// 加锁
lock.lock();
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
ticket–;
System.out.println(Thread.currentThread().getName() + “------” + ticket);
} else {
break;
}
} finally {
lock.unlock();
}
}
}}
synchronized和Lock的异同?
synchronized是代码块执行完自动释放
Lock是代码块执行完手动释放
继承的解决
- 同步代码块
class window1 extends Thread { private static int ticket = 100; // 使用懒汉模式 // private static Object oj = new Object(); @Override public void run() { while (true) { // 使用类名 synchronized (window1.class) { if (ticket > 0) { try { Thread.sleep(100); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } ticket--; System.out.println(Thread.currentThread().getName() + "------" + ticket); } else { break; } } } } }
同步方法
class window1 extends Thread { private static int ticket = 100; // 使用懒汉模式 // private static Object oj = new Object(); @Override public void run() { while (true) { if (!show()) { break; } } } private static synchronized boolean show() { // this 指向 window1.class if (ticket > 0) { try { Thread.sleep(100); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } ticket--; System.out.println(Thread.currentThread().getName() + "------" + ticket); return true; } else { return false; } } }
死锁的问题
-
演示死锁发生的情况
class Xiance { public static void main(final String[] args) { final StringBuffer s1 = new StringBuffer(); final StringBuffer s2 = new StringBuffer(); new Thread() { @Override public void run() { // 第一个线程拿到s1 // 第二个线程拿到s2 // 谁也不释放锁所以导致死锁 synchronized (s1) { s1.append("1"); s2.append("a"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s2) { s1.append("2"); s2.append("b"); } } System.out.println(s1.toString()); System.out.println(s2.toString()); } }.start(); ; new Thread(new Runnable() { @Override public void run() { synchronized (s2) { s1.append("1"); s2.append("a"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s1) { s1.append("2"); s2.append("b"); } } System.out.println(s1.toString()); System.out.println(s2.toString()); } }).start(); ; } }
解决方式:
尽量避免嵌套,使用银行家算法