一、创建线程
1、继承thread类,重新写run方法
public class Test_CreateThread extends Thread {
@Override
public void run() {
//重写run方法 run方法线程体
for (int i = 0; i < 500; i++) {
System.out.println("我在看视频->"+i);
}
}
public static void main(String[] args) {
Test_CreateThread test_createThread=new Test_CreateThread();
//test_createThread.start();
test_createThread.run();
//main主线程体
for (int i = 0; i < 500; i++) {
System.out.println("我在学习多线程->"+i);
}
}
}
2、实现Runnable接口,重写run方法 使用Thread代理
public class Test_CreateThread2 implements Runnable {
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 5; i++) {
System.out.println("我在看视频->" + i);
}
}
public static void main(String[] args) {
Test_CreateThread2 test_createThread2 = new Test_CreateThread2();
// Thread thread=new Thread(test_createThread2);
// thread.start();
new Thread(test_createThread2).start();
for (int i = 0; i < 5; i++) {
System.out.println("我在学习->"+i);
}
}
}
注意:
启动线程的方法不同,调用run()方法时,如果子线程在主线程体之前启动,则会先运行子线程,然后才会执行主线程体语句。
调用start()方法时线程不一定立即执行,由cpu安排调度,就会出现交替执行的情况。如下图
二、Lambda表达式 推导
1、外部类
public class Test_Lambda {
//调用
public static void main(String[] args) {
IRead iRead=new Read();
iRead.read();
}
}
//1、定义一个函数式接口
interface IRead{
void read();
}
//2、实现类 外部类
class Read implements IRead{
@Override
public void read() {
System.out.println("I read book1!");
}
}
外部类修饰符:只能用public、abstract、final修饰
2、静态内部类
public class Test_Lambda {
//2、实现类 内部类
static class Read implements IRead {
@Override
public void read() {
System.out.println("i read book2");
}
}
public static void main(String[] args) {
IRead iRead = new Read();
iRead.read();
}
}
//1、函数式接口
interface IRead {
void read();
}
静态内部类必须加static修饰
内部类修饰符:private、protected、public、final、static、abstract
3、局部内部类
public class Test_Lambda {
public static void main(String[] args) {
//2、实现类 局部内部类
class Read implements IRead{
@Override
public void read() {
System.out.println("i read book3!");
}
}
IRead iRead = new Read();
iRead.read();
}
}
//1、函数式接口
interface IRead {
void read();
}
4、匿名内部类
public class Test_Lambda {
public static void main(String[] args) {
//2、实现类 匿名内部类
new IRead() {
@Override
public void read() {
System.out.println("i read book4!");
}
}.read();
}
}
//1、函数式接口
interface IRead {
void read();
}
5、lambda表达式
public class Test_Lambda {
public static void main(String[] args) {
//2、lambda表达式
IRead read = () -> {
System.out.println("i read book5!");
};
read.read();
}
}
//1、函数式接口
interface IRead {
void read();
}
- lambda表达式主体只有一句时,{}可以省略
IRead read = () -> System.out.println("i read book5!");
- 参数类型可以省略 有多个参数时,要省略参数类型就必须全部省略
//IRead read = (int a) -> System.out.println("i read book5!->"+a);
IRead read =(a) -> System.out.println("i read book5!->"+a);
- 只有一个参数时,()可以省略
IRead read =a-> System.out.println("i read book5!->"+a);
三、线程优先级
- 线程的优先级值为从1-10的整数,越大则优先级越大。若超出1-10这个范围,就会抛出异常
- 优先级只能表示线程先执行的可能性越大,但也会出现低优先级先执行的情况。得看cpu调度的心情
- main主线程的优先级固定不变,为5
public class Test_Priority {
public static void main(String[] args) {
//打印主线程的优先级
System.out.println(Thread.currentThread().getName()+"-> "+Thread.currentThread().getPriority());
TestPriority tp=new TestPriority();
Thread t1=new Thread(tp);
Thread t2=new Thread(tp);
Thread t3=new Thread(tp);
Thread t4=new Thread(tp);
Thread t5=new Thread(tp);
//设置优先级 并启动
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(5);
t3.start();
t4.setPriority(10);
t4.start();
t5.setPriority(8);
t5.start();
}
}
class TestPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-> "+Thread.currentThread().getPriority());
}
}
四、线程的同步 synchronized
1、synchronized方法
- synchronized方法控制对 对象 的访问,每个对象都有一把锁。
- 添加了synchronized方法后,每个线程调用对象时都需要获得对象的锁,获得之后才能执行,且一直独占对象的锁,直到方法执行完后才会释放,后续线程才能获得这个锁。
- 方法声明为synchronized会影响效率
public class Test_synchronized {
public static void main(String[] args) {
buyTickets buyTickets=new buyTickets();
new Thread(buyTickets,"小帆").start();
new Thread(buyTickets,"小卿").start();
new Thread(buyTickets,"小陈").start();
}
}
class buyTickets implements Runnable {
private int ticketNum = 10; //票的总数
boolean flag = true; //线程停止标志
@Override
public void run() {
while (flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//添加synchronized 同步方法 锁的是buyTickets对象
private synchronized void buy() throws InterruptedException {
if(ticketNum<=0){
flag=false; //票总数为0时,线程结束
return;
}
Thread.sleep(100); //模拟延时,放大问题发生性
System.out.println(Thread.currentThread().getName()+"买到了第"+ticketNum-- +"张票");
}
}
如果不添加synchronized方法锁,就会出现买到负数的票和多人买到同一张票的情况。如下图:
添加synchronized方法后的运行结果如下: