java runnable线程锁_多线程 java 同步 、锁 、 synchronized 、 Thread 、 Runnable

线程

1 线程概述

1.1 什么是线程

v  线程是程序执行的一条路径, 一个进程中可以包含多条线程

v  一个应用程序可以理解成就是一个进程

v  多线程并发执行可以提高程序的效率, 可以同时完成多项工作

1.2 多线程应用场景

VNC同时共享屏幕给多个电脑

迅雷开启多条线程一起下载

QQ同时和多个人一起视频

服务器同时处理多个客户端请求

1.3并行和并发的区别

并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行。(需要多核CPU)

并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于间时间隔较短,使人感觉两个任务都在运行(画图-任务调度)。

1.4 Java程序运行原理

Java命令会启动java虚拟机(JVM),等于启动了一个应用程序,也就是启动了一个进程。

该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 main 方法

一个应用程序有且只有一个主线程,程序员不能New主线程,可以New子线程。

1.5 JVM启动的是多线程吗?

JVM启动至少启动了垃圾回收线程和主线程,所以是多线程的。

main方法的代码执行的位置就是在主线程(路径)

一个进程有多个线程

finalize()这个方法在子线程(垃圾回收线程)执行

public class Demo01 {

public static void main(String[] args) {

/*JVM的启动是多线程的吗?【面试题】*/

System.out.println("AAAAA");

System.out.println("BBBBB");

System.out.println("CCCCC");

System.out.println("DDDDD");

//打印线程名称

System.out.println(Thread.currentThread());//主线程

for(int i = 0;i<2;i++){

new Student();

System.gc();//启动垃圾回收

}

}

}

class Student{

//被垃圾回收器回收时,会调用

//对象从内存释放时,会调用

@Override

protected void finalize() throws Throwable {

// TODO Auto-generated method stub

System.out.println("student 被回收了...");

//打印线程名称

System.out.println(Thread.currentThread());//子线程

}

}

2 Java中线程的实现方式

2.1方式一、继承Thread

使用步骤:

1.定义类继承Thread

2.重写run方法

3.把新线程要做的事写在run方法中

4.创建线程对象

5.开启新线程, 内部会自动执行run方法

代码:

public class Demo01 {

public static void main(String[] args) {

/*主线程,程序员不能创建,程序员只能创建子线程*/

//1.创建子线程对象

MyThread t1 = new MyThread();

/**不能通过下面的方式来执行任务

* 因为这种试的任务是在主线程执行的*/

//t1.run();

//2.正确的执行任务的方式,调用start,内部会开启新线程,调用run方法

t1.start();

//3.再创建子线程

MyThread t2 = new MyThread();

t2.start();

//4.循环创建子线程

for(int i=0;i<10;i++){

MyThread th = new MyThread();

th.start();

}

}

}

class MyThread extends Thread{

@Override

public void run() {

System.out.println("银行信用卡还款短信任务..." + Thread.currentThread());

System.out.println("线程名称" + this.getName());

}

}

2.2方式二、实现Runnable接口

实现步骤:

1.定义类实现Runnable接口

2.实现run方法

3.把新线程要做的事写在run方法中

4.创建自定义的Runnable的子类对象,创建Thread对象传入Runnable

5.调用start()开启新线程, 内部会自动调用Runnable的run()方法

代码:

public class Demo01 {

public static void main(String[] args) {

/*      线程实现的方式 (2) - 定义类实现Runnable接口

//1.创建runable对象

BankTask task = new BankTask();

//2.创建Thread对象

Thread t1 = new Thread(task);

//3.启动线程

t1.start();

//4.再开启2个线程

Thread t2 = new Thread(task);

t2.start();

Thread t3 = new Thread(task);

t3.start();

}

}

class BankTask  implements Runnable{

@Override

public void run() {

// TODO Auto-generated method stub

System.out.println("银行储蓄卡自动结算利息任务..." + Thread.currentThread());

//System.out.println("线程名称:" + this.getName());

System.out.println("线程名称:" +Thread.currentThread().getName());

}

}

2.3两种方式的区别

区别:

继承Thread : 由于子类重写了Thread类的run(), 当调用start()时直接找子类的run()方法

实现Runnable : 构造函数中传入了Runnable的引用, 有个成员变量记住了它, 调用run()方法时内部判断成员变量Runnable的引用是否为空。

继承Thread

好处是:可以直接使用Thread类中的方法,代码简单

弊端是:如果已经有了父类,就不能用这种方法

实现Runnable接口

好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口,代码更灵活

弊端是:不能直接使用Thread中的方法,需要先获取到线程对象后,才能得到Thread的方法,代码复杂

2.4 匿名内部类实现线程的两种方式

public static void main(String[] args) {

//匿名内部类实现线程的两种方式

/*Thread t1 = new Thread(){

@Override

public void run() {

System.out.println("任务1...." + Thread.currentThread());

}

};

t1.start();*/

new Thread(){

public void run() {

System.out.println("任务1...." + Thread.currentThread());

};

}.start();

/*Thread t2 = new Thread(new Runnable() {

@Override

public void run() {

System.out.println("任务2...." + Thread.currentThread());

}

});

t2.start();*/

new Thread(new Runnable() {

@Override

public void run() {

System.out.println("任务2...." + Thread.currentThread());

}

}).start();

}

2.5 获取线程名字和设置名字

通过Thread的getName()方法获取线程对象的名字

通过setName(String)方法可以设置线程对象的名字

通过构造函数可以传入String类型的名字

每个线程系统都会默认分配个名字,主线程:main,子线程thread-0 ....

public class Demo01 {

public static void main(String[] args) {

/*     获取线程名字和设置名字(掌握)

//1.获取主线程对象

Thread mainThread = Thread.currentThread();

System.out.println(Thread.currentThread());

System.out.println(mainThread);

System.out.println("名称:" + mainThread.getName());

//2.设置线程的名称

mainThread.setName("主线程");

System.out.println(mainThread);

//3.设置子线程的名称

MyThread myThread = new MyThread("子线程1");

myThread.start();

}

}

class MyThread extends Thread{

public MyThread(String name) {

super(name);

}

@Override

public void run() {

System.out.println("银行代发工资任务..." + Thread.currentThread());

}

}

2.6 获取当前线程的对象

Thread.currentThread()方法用于获取当前线程对象

在不同的方法中,获取的线程对象名称是有可能不一样的

在main中获取的是主线程对象

在子线程的run方法中获取的是子线程对象

public class Demo01 {

public static void main(String[] args) {

//获取当前线程的对象(掌握)

Thread mainThread = Thread.currentThread();

mainThread.setName("主线程");

//打印主线程对象

System.out.println(mainThread);

//打印主线程对象类名

System.out.println(mainThread.getClass());

System.out.println("================");

//开启子线程

MyThread mt = new MyThread();

mt.start();

}

}

class MyThread extends Thread{

@Override

public void run() {

System.out.println("任务...");

Thread subThread = Thread.currentThread();

//打印子线程对象

System.out.println(subThread);

//打印子线程对象类名

System.out.println(subThread.getClass().getName());

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值