匿名内部类
内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。
格式:
new 父类名 或 接口名(){
重写父类的方法
};
代码举例:
// 利用给TreeSet 集合中的学生对象 按年龄排序
public class Demo02 {
public static void main(String[] args) {
TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
});
set.add(new Student("james", 19));
set.add(new Student("Tom", 21));
set.add(new Student("jerlly", 18));
set.add(new Student("mike", 22));
for (Student student : set) {
System.out.println(student);
}
}
利用匿名内部类创建线程:
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("启动");
}
});
thread.start();
线程的六种状态
1.新建状态 (new 线程对象)
2.运行状态 (调用 start()方法)
3.受阻塞状态 (等待CPU的执行资源)
4.休眠状态 (调用了sleep()方法)
5.等待状态 (调用了wait()方法)
6.死亡状态 (run()方法执行完毕)
线程休眠
线程休眠指线程调用了sleep()方法 让它在一定毫秒内执行线程休眠(暂停执行)
代码示例:
public class Demo04 {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
// 线程休眠 1000 毫秒
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
class SleepThread extends Thread{
/*
* 如果子线程出现异常 只能try...catch(){} 处理
*
* Thread 是Runnable 接口的实现类 重写了接口中的run()方法
* 该方法没有抛出异常 所以所有Runnable 实现类(包括Thread类) 都不能在run()方法中抛出异常 只能自己处理
*/
@Override
public void run() {
for (int i = 0; i < 50; i++) {
// 线程休眠 1000 毫秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
多线程访问同一共享数据遇到的问题:
引入 synchronized 同步锁 概念
// 三种方式买票 分别使用三个线程 访问同一终端
public class Demo05 {
public static void main(String[] args) {
// 创建三条线程
Ticket ticket = new Ticket();
Thread t1 = new Thread(ticket);
Thread t2 = new Thread(ticket);
Thread t3 = new Thread(ticket);
t1.start();
t2.start();
t3.start();
}
}
/* 同步锁(同步代码块)
* 锁 可以是任意对象 要保证 锁的唯一 三个线程 都使用的是同一把锁
* synchronized (对象锁){
*
* }
* 同步锁规则
* 如果有锁 可以进去 携带锁进去 等出了同步代码块 当线程执行完代码块中的代码 把锁还回去
* 线程没有遇到锁 会在同步代码块等待 遇到锁才能进
*
*/
class Ticket implements Runnable{
// 保证票
private int ticks = 100;
// 创建了对象锁 保证了唯一
private Object obj = new Object();
@Override
public void run() {
while (true) {
// 锁只要保证是对象和唯一就可以 填 this也可以
synchronized (obj) {
// 操作的共享数据的代码
if (ticks > 0) {
// 线程休眠
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 有票就卖
System.out.println(Thread.currentThread().getName() + "---" + ticks);
ticks --;
}else {
// 没票 结束循环
break;
}
}
// 让线程让出cpu资源
Thread.yield();
}
}
}
/*
* 解析:
* 如果不加 同步锁 会出现什么情况?
* 会出现一张票被三个线程同时买到现象
* 那么为什么会出现这种情况呢?
* 首先 三个线程调用start()方法 执行程序是随机的 系统调度会 随机让某个线程CPU提供的资源
* 转移给另一个线程 但是这个线程恰好在获取余票却没有进行 总票 -1 情况 下一个线程也读取了
* 同样的余票总数 因此出现错误 使用同步锁就不会出现这种情况!
*/
上面介绍了同步锁代码块的写法和作用 下面介绍同步锁的另一种写法:
// 在方法中添加 synchronized 关键词 把方法变成同步方法
public static synchroized void name(){
//do something
}
//当方法是静态方法时 使用同步代码块时 可以不必创立一个对象锁传入同步代码块中
// 可以直接使用 本类 类名.class
synchroized(类名.class){
// do something
}
死锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
模拟死锁代码:
public class Demo07 {
public static void main(String[] args) {
TestSync test = new TestSync();
Thread thread = new Thread(test);
Thread thread2 = new Thread(test);
thread.start();
thread2.start();
}
}
class TestSync implements Runnable{
private boolean isTrue = true;
@Override
public void run() {
while (true) {
if (isTrue) {
// A锁 ---> B锁
synchronized (LockA.LOCK_A) {
System.out.println("if....LOCK_A");
synchronized (LockB.LOCK_B) {
System.out.println("if...LOCK_B");
}
}
}else {
// B锁 ---> A锁
synchronized (LockB.LOCK_B) {
System.out.println("else...LOCK_B");
synchronized (LockA.LOCK_A) {
System.out.println("else...LOCK_A");
}
}
}
// 修改标记
isTrue = !isTrue;
}
}
}
// A锁对象
class LockA{
public LockA() {
}
public static final LockA LOCK_A = new LockA();
}
class LockB{
public LockB() {
}
public static final LockB LOCK_B = new LockB();
}
Lock 接口
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。 从java 1.5 开始
实现步骤:
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
代码示例:
public class Demo08 {
public static void main(String[] args) {
Titkets1 test = new Titkets1();
Thread thread = new Thread(test);
Thread thread2 = new Thread(test);
Thread thread3 = new Thread(test);
thread.start();
thread2.start();
thread3.start();
}
}
class Titkets1 implements Runnable{
private int num = 100;
//声明锁对象
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
// 加锁
lock.lock();
try {
// 锁住操作共享数据的代码
if (num >0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "---" + num --);
}else {
break;
}
} finally {
lock.unlock();
}
Thread.yield();
}
}
}