多线程
* 第一种继承Thread类 重写run方法
*
* 并发:一个CPU同时执行多个任务
* 并行:多个CPU同时执行多个任务
public class Thread_01 {
public static void main(String[] args) {
//创建线程对象
Thread t = new Processor();
//启动线程,只有这一种方法,会自动执行run方法 但是注意我们不能手动调用run方法
t.start();
for (int i = 0; i < 10; i++) {
System.out.println("main线程"+i);
}
}
}
class Processor extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
System.out.println("测试线程"+i);
}
super.run();
}
}
第二种创建线程的方式
*
* 实现Runable接口并覆写了run方法
*
* 启动还是 stract()
public class Thread_02 {
public static void main(String[] args) {
//创建线程对象
Thread thread = new Thread(new Processor_01());
//启动方式
thread.start();
for (int i = 0; i <10; i++) {
System.out.println("main测试"+i);
}
}
}
class Processor_01 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i <10; i++) {
System.out.println("线程测试"+i);
}
}
}
优先级 java中分为10 个等级,分别是1-10
*
* 另外Thread类还提供了三个常量 ,分别保存了1,5,10优先级
*
* 最高 10 Thread.MAX_PRIORITY
* 正常 5 Thread.NORM_PRIORITY
* 最低 1 Thread.MIN_PRIORITY
*
* getPriority() 获取该线程优先级
*
*
* setPriority() 设置对应的优先级
*
* 低优先级只是获取调度的概率低,并非一定是在高优先级之后被执行
*
*
*
*
* 生命周期
*
* 创建 就绪 运行 阻塞 复活 阻塞 死亡
*
* 常用方法
*
* start()启动线程唯一方式
*
* setName 设置线程名字
*
* getName 获取线程名字
*
* setPriority 设置线程优先级
*
* Static currentThread()获取当前线程对象
*
* static sleep()让当前线程进入睡眠,参数是毫秒数
*
public class Thread_03 {
public static void main(String[] args) {
Thread thread = new Processer_02();
//设置优先级为10
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
//currentThread静态方法获取当前对象
//设置main方法优先级为1
Thread.currentThread().setPriority(1);
for (int i = 0; i <10; i++) {
System.out.println("main线程"+i);
}
}
}
class Processer_02 extends Thread{
@Override
public void run() {
for (int i = 0; i <10; i++) {
System.out.println("测试线程"+i);
}
}
}
* sleep()让当前线程睡眠
*
* 唤醒睡眠的两种方式
*
* 1正常唤醒 就是睡眠时间到了
* 2异常唤醒 强制打断睡眠 ,会报异常
* java.lang.InterruptedException: sleep interrupted
*
* interrupt:强制唤醒某个线程
public class Thread_05 {
public static void main(String[] args) {
Thread t = new Processer_03();
t.start();
try {
//睡眠1秒
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//1秒 后 唤醒t线程
t.interrupt();
}
}
class Processer_03 extends Thread{
@Override
public void run() {
try {
Thread.sleep(4000);
System.out.println("睡醒了");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("闹钟响了");
}
System.out.println("开始上班");
}
}
Join:线程合并,让指定线程在该线程运行完之后在运行'
*
* Join写在哪里就让哪个线程等待
public class Thread_06 {
public static void main(String[] args) throws InterruptedException {
//创建线程
Thread thread = new Thread(new Processer_04());
//设置名字为t1
thread.setName("t1");
thread.start();
//让main等待 因为是写在main方法里
thread.join();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Processer_04 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
同步的目的都是为了数据
*
* 线程同步:
* 当多个线程操作同一个数据的时候,为了保证数据的一致
*
* 线程同步本质就是数据同步,是一种安全机制
*
* 异步编程
* 线程之间是完全独立的,谁运行也不会受到别的线程的影响
* 同步编程
* 线程之间不是独立的,相互之间是有影响的,某个功能必须只能让一个线程执行同时执行,主要为了数据安全
*
* 同步的原因
* 1数据同步,为了数据安全,某种情况来讲,同步可以理解为暂时把多线程转换为单线程
*
*
* 2同步条件 什么时候需要同步
* 1必须多线程(单线程没有啥并发和冲突的情况)
* 2多个线程有可能同时操作同一个数据的可能性
* 3主要是数据的更改操作
*
*
*
* 只要对方法加上synchronized的成员方法,就代表该方法不能被多个线程同时访问
*
*
* 使用方法 同步代码段
*
*
*
* 锁是每个对象都有的,synchronized只是把锁锁住的一个持续动作,而多个线程必须保存同一个对象,才能使用同一把锁
*
*
* 如果多个线程之间保存的不是同一个对象,尽管是同一个类的不同对象,也是没又办法相互排斥的
public class Thread_09_Synchronization {
public static void main(String[] args) {
//创建账户对象 余额为5000
Account account = new Account(5000);
//两个线程对象保存的是同一个账户对象
Thread t1 = new Thread(new Processor_07(account));
Thread t2 = new Thread(new Processor_07(account));
//设置名字
t1.setName("t1");
t2.setName("t2");
//启动线程
t1.start();
t2.start();
}
}
class Processor_07 implements Runnable{
//保存账户 对象
private Account account;
public Processor_07(Account account) {
super();
this.account = account;
}
@Override
public void run() {
// TODO Auto-generated method stub
//取钱1000 , 取钱方法
account.withDraw(1000);
System.out.println(Thread.currentThread().getName()+ "取款成功,取款1000元 余额是"+account.getBalance());
}
}
//实体类
class Account{
//余额
private double balance;
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public Account(double balance) {
super();
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
balance = after;
}
}
* Lock 可以锁代码块,并且性能较好,不用频繁调用线程
* 并且开始加锁和关闭锁, 都是需要手动的, 又称为显示锁
*
* 而synchronized是隐式锁 超出作用域,自动解锁
*
* 1Lock是显示锁(手动开启和关闭锁, 别忘记关闭锁), synchronized是隐式锁,出了作用域自动释放
*
* 2Lock只有代码块锁,synchronized有代码块锁和方法锁
*
* 3使用Lock锁 JVM将花费较少的时间来调度线程,性能更好,并且具有更好的扩展类(提供更多的子类)
*
* synchronized 可以所方法
*
*
* 优先使用顺序
* Lock 同步代码块(已经进入方法体,分配了相应的资源)
public class Thread_10_Lock {
public static void main(String[] args) {
ATM atm = new ATM(5000);
Thread t1= new Thread(new Processor_08(atm));
Thread t2= new Thread(new Processor_08(atm));
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}
//线程类
class Processor_08 implements Runnable{
//保存账户对象
private ATM atm;
public Processor_08(ATM atm) {
super();
this.atm = atm;
}
@Override
public void run() {
// TODO Auto-generated method stub
//取钱1000
atm.withDraw(1000);
}
}
class ATM{
private double balance;
//锁
//创建锁
private Lock lock = new ReentrantLock();
public ATM(double balance) {
super();
this.balance = balance;
}
public synchronized void withDraw(double money){
System.out.println(Thread.currentThread().getName()+"进来了");
/**
*
* 非访问数据区域,不需要同步
*
*
* 开启锁数据同步
*/
lock.lock();
try {
double after = balance - money;
balance = after;
System.out.println(Thread.currentThread().getName()+"取钱成功,取钱"+money+"剩余"+balance+"元");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//必须执行的代码段
} finally{
//解锁
lock.unlock();
}
//非访问数据区域,不需要同步
}
}