线程
优先级
生命周期
睡眠
线程合并
Yield
Stop
线程同步
创建线程对象的两种方式:
1、Processer02继承Thread类,并覆写run()方法
创建线程对象,调用子类构造方法创建对象
父类引用指向子类对象,多态
线程类 对象=new 线程类子类的构造方法
Thread thread=new Processer02();
2、Processor07实现Runnale接口并覆写run()方法
创建线程对象用Thread类的有参构造方法,传入实现Runnable接口类的对象
Thread t1 = new Thread(new Processor07());
第一种如下:
public class Thread01create {
public static void main(String[] args) {
//创建线程有两种方式:
// 第一种 继承Thread类,并覆写run()方法
//启动线程只有一种方式,就是调用线程对象中的start()方法
// 创建线程对象
//多态,父类引用指向子类对象
Thread t = new Processor();
// 启动,会自动执行run()方法,但是注意 我们不能手动调用run()方法
t.start();
for (int i = 0; i < 10; i++) {
System.out.println("main线程 : " + i);
}
}
}
class Processor extends Thread {
//覆写run方法
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("测试线程 : " + i);
}
}
}
第二种方法如下:
public class Thread02create {
//第二种创建线程的方式:实现Runnale接口并覆写run()方法
//启动 还是使用线程对象中的start()方法
public static void main(String[] args) {
//创建线程对象thr
//Thread的有参构造方法中传入实现Runnable接口的类的对象
//传入接口实现类的对象时,我们可以不传入对象,传入一个匿名内部类
// Thread thr1=new Thread(new Processor01());
Thread thr=new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<8;i++){
System.out.println("测试线程"+i);
}
}
});
//启动线程
thr.start();
for(int i=0;i<8;i++){
System.out.println("main线程"+i);
}
}
}
//class Processor01 implements Runnable{
//
// @Override
// public void run() {
// for(int i=0;i<8;i++){
// System.out.println("测试线程"+i);
// }
// }
//
//}
启动线程只有一种方式,就是调用线程对象中的start()方法
优先级:java中分为10个等级,分别是1-10
在Thread类中还提供了三个常量,分别保存1、5、10优先级
最高优先级:最高:10 Thread.MAX_PRIORITY
正常: 5 Thread.NORM_PRIORITY
最低:1 Thread.MIN_PRIORITY
getPriority():获取该线程优先级
setPriority():设置该线程优先级
线程创建时继承父线程的优先级,Thread的优先级是5
低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用
public class Thread03Priority {
public static void main(String[] args) {
//创建线程对象,调用子类构造方法创建对象
//父类引用指向子类对象,多态
//线程类 对象=new 线程类子类的构造方法
Thread thread=new Processer02();
//设置thread线程对象的优先级为最大优先级10
thread.setPriority(Thread.MAX_PRIORITY);
//启动线程
thread.start();
//currentThread:调用Thread类的静态方法获取当前线程对象
//设置main方法的main方法优先级为1
Thread.currentThread().setPriority(1);
for (int i = 0; i < 10; i++) {
System.out.println("main线程"+i);
}
}
}
class Processer02 extends Thread{
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println("测试线程"+i);
}
}
}
线程 生命周期:创建,就绪,运行,阻塞,死亡
static currentThread():静态方法,用于获取当前线程的对象,写在哪个线程中,就获取哪个线程的对象
static sleep(long m):静态方法,让当前线程睡眠,需要传入对应的毫秒数,写在哪个线程就睡眠哪个线程
public class Thread04lifecycle {
public static void main(String[] args) {
//创建线程对象
Thread t1=new Thread(new Processer());
Thread t2=new Thread(new Processer());
//t1和t2在创建线程对象时,就已经生成名字,Thread-0和Thread-1
//设置线程的名字
t1.setName("t1");
t2.setName("t2");
//启动线程,进入就绪状态
t1.start();
t2.start();
for (int i = 0; i < 10; i++) {
//currentThread是Thread类里的静态方法,获取当前线程对象
//getName方法获取当前线程对象的名字,也就是main
System.out.println(Thread.currentThread().getName());
try {
//main方法休眠1秒
//sleep是Thread类里的静态方法,传入睡眠时间,毫秒,睡眠1秒,进入阻塞
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//实现Runnable接口的类
class Processer implements Runnable{
//获取当前线程对象,并调用getName方法
//由于没有继承Thread类,所以不能使用this直接调用Thread类中的方法,因为没有继承Thread
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//输出当前线程对象的名字
System.out.println(Thread.currentThread().getName());
}
}
}
唤醒睡眠的线程有两种方式
1 正常唤醒:就是睡眠时间到了
2 异常唤醒:强制打断睡眠,会报异常
interrupt :强制唤醒某个线程
public class Thread05interrupt {
public static void main(String[] args) {
Thread t=new Processer03();
//线程启动
t.start();
try {
//线程睡眠1秒
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
//1秒后,唤醒t线程
t.interrupt();
}
}
class Processer03 extends Thread{
public void run(){
try {
//线程睡眠3秒
Thread.sleep(3000);
System.out.println("正常睡醒");
//睡眠被唤醒,会报异常
} catch (Exception e) {
e.printStackTrace();
System.out.println("闹钟响,被打断,异常醒");
}
System.out.println("上班");
}
}
join 线程合并,让指定线程在该线程运行完之后再执行
public class Thread06join {
public static void main(String[] args) throws InterruptedException{
Thread thread= new Thread(new Processer04());
thread.setName("t1");
thread.start();
//线程合并,让指定线程在该线程运行完之后再执行
//让main在thread线程运行完之后再执行
thread.join();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName());
try {
//线程睡眠半秒
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class Processer04 implements Runnable{
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
*Thread.Yield 暂停当前正在执行的线程,并执行其他线程
*同优先级的线程才可以让位,不同优先级不让位
*静态方法意味着写在哪个线程,哪个线程就让位
*该当前线程执行的时候,把该执行机会(时间片)让给其他线程
public class Thread07Yield {
public static void main(String[] args) {
Thread tr=new Processor05();
tr.setName("rgf");
tr.start();
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
}
class Processor05 extends Thread{
public void run(){
for(int i=0;i<10;i++){
//静态方法,写在哪哪让位
Thread.yield();
//由于继承的Thread类,所以可以直接调用getName方法
System.out.println(getName());
}
}
}
stop: 终止一个线程,不推荐使用
可以使用标识符的形式来结束
public class Thread08Stop {
public static void main(String[] args) {
Processor06 t1=new Processor06();
t1.setName("t1");
t1.start();
try{
//sleep是Thread类的静态方法
//线程睡眠3秒
Thread.sleep(3000);
}catch(Exception e){
e.printStackTrace();
}
//3秒后终止t1线程
//使用stop终止容易出现问题
//t1.stop();
//推荐使用标识符解决
//将t1对象的isStop属性修改为true
t1.isStop=true;
}
}
class Processor06 extends Thread{
boolean isStop=false;
public void run(){
while(true){
//如果标识符是true,那么我们就终止线程执行
if(isStop){
return;
}
//继承了Thread类,可以直接用getName方法
System.out.println(getName());
}
}
}
线程同步 : 当多个线程操作同一个数据的时候,为了保证数据的一致 线程同步本质就是数据同步,是一种安全机制
异步编程 : 线程之间是完全独立的,谁的运行也不会受到别的线程的影响
同步编程 : 线程之间不是独立的,相互之间是有影响的,某个功能必须只能让一个线程同时执行,主要为了数据安全
同步的原因 : 1 数据同步,为了数据安全,某种情况来讲,同步可以理解为暂时把多线程转换为单线程 2 什么时候需要同步 1
必须多线程(单线程没有啥并发和冲突的情况) 2 多个线程有可能同时操作同一个数据的可能性 3 主要是数据的更改操作
只要对方法加上 synchronized的成员方法,就代表该方法不能被多个线程同时访问
锁是每个对象都有的,synchronized只是把锁锁住的一个持续动作,而多个线程必须保存同一个对象,才能使用同一把锁,才能相互排斥,才能保证数据安全
如果多个线程之间保存的不是同一个对象,尽管是同一个类的不同对象,也是没有办法相互排斥的
public class Thread09Syn {
public static void main(String[] args) {
// 创建账户对象,余额为5000
Account account = new Account(5000);
// 两个线程对象保存同一个账户对象
//创建线程对象用Thread类的有参构造方法,传入实现Runnable接口类的对象
Thread t1 = new Thread(new Processor07(account));
Thread t2 = new Thread(new Processor07(account));
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}
class Processor07 implements Runnable{
// 保存账户 对象
private Account account;
public Processor07(Account account) {
this.account = account;
}
//线程执行那么就调用account对象的取款方法
//之后返回余额
@Override
public void run() {
account.withDraw(1000);
System.out.println(Thread.currentThread().getName()
+ " 取款成功,取款1000元,余额是 : " + account.getBalance());
}
}
//账户类
class Account {
private double balance;
public Account(double balance) {
this.balance = balance;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
//取钱方法
//传入取的钱,加锁保证同步,主要是对余额的修改操作需要同步、
//多个线程同时操作一个属性
public synchronized void withDraw(double money) {
double after = balance - money;
System.out.println(Thread.currentThread().getName()+" 我来取钱啦~");
try {
//加上睡眠可以使余额显示的正常
//不加睡眠的话第一个线程访问完加锁方法后想要获取余额进行显示之前
//第二个线程已经访问完加锁方法并已经修改了余额
//那么可能会出现两个线程显示余额时一样
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
balance = after;
}
}