Java中线程的基本理解和synchronized关键字使用

Java中线程的实现方式

  1. 继承Thread类,重写run方法。在run方法中实现具体逻辑
    public class ExtendThread {
    public static void main(String[] args) {
    ThreadTest threadTest = new ThreadTest();
    threadTest.start();
    }
    }
    class ThreadTest extends Thread{
    @Override
    public void run() {
    System.out.println(“thread”);
    }
    }
  2. 实现runnable接口。
    public class RunnableTest {
    public static void main(String[] args) {
    ThreadImRunnable runnable = new ThreadImRunnable();
    Thread thread = new Thread(runnable);
    thread.start();
    for (int i = 0; i < 10; i++) {
    System.out.println(Thread.currentThread().getName()+“main***********”+i);
    }
    }

}
class ThreadImRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(“我是Runnable”+i);
}

}

}

线程和进程理解
● 只有当所有线程结束,进程才会结束
● start()开启多线程。最终调用jvm的start0(),使该线程处于可运行状态。等待cpu调度。
● 主线程启动子线程的运行。只有当主线程和子线程都结束了。整个进程才会结束。
● 继承Thread和实现Runnable接口的区别。继承Thread类只能线程独享资源。每个Thread都会创建新的资源。实现Runnable接口可以实现多线程共享资源的情况。避免了但继承的限制。
通知线程退出
在实现Runnable接口的或者继承Thread的类里面添加一个属性,并且设置getset方法。在主线程某个时刻修改这个属性。使其停止执行。
public class ThreadExit {
public static void main(String[] args) throws InterruptedException {
ThreadExit_ threadExit_ = new ThreadExit_();
threadExit_.start();

    Thread.sleep(5*1000);
    //设置为false,满足使其停止循环的条件。退出线程
    threadExit_.setLoop(false);

}

}
class ThreadExit_ extends Thread{
private int count = 0;

public void setLoop(boolean loop) {
    this.loop = loop;
}

//通知线程终止属性
private boolean loop = true;
@Override
public void run() {

    while (loop){
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("子线程"+(++count));

    }
}

}
线程的礼让和插入
线程礼让:指的是某一个线程礼让另一个线程。但是只是让出竞争资源。实际还要根据cpu调度来看。礼让不一定成功。也有可能两个线程还是同时执行

线程插入:指的是某一个线程执行Thread.join()方法。停止执行当前线程。直到join进来的线程全部执行完毕再执行之前的线程。
public class JoinThread {
public static void main(String[] args) throws InterruptedException {
ThreadJoin threadJoin = new ThreadJoin();
threadJoin.start();
for (int i = 0; i < 20; i++) {
System.out.println(“主线程在吃包子”+i);
Thread.sleep(1000);
if(i==10){
System.out.println(“主线程让子线程插队吃”);
//执行join方法
threadJoin.join();
}
}
}
}
class ThreadJoin extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(“子线程在吃包子”+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
用户线程和守护线程
用户线程:也叫工作线程,正常执行完或者以通知方式退出。
守护线程:当所有线程执行完,该线程也会自动退出。
使用实例:垃圾回收机制
public class DeamonThread {
public static void main(String[] args) throws InterruptedException {
T t = new T();

    Thread thread = new Thread(t);
    //设置为守护线程。注意要在线程启动之前
    thread.setDaemon(true);
    thread.start();

    for (int i = 0; i < 10; i++) {
        Thread.sleep(1000);
        System.out.println("俺们在干活");
    }

}

}
class T implements Runnable{

@Override
public void run() {
    for(;;){
        try {
            Thread.sleep(1000);
            System.out.println("俺们在聊天");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

}
使用synchronized�买卖售票问题
public class SellThread {
public static void main(String[] args) {
SellTicketThread sellTicketThread01 = new SellTicketThread();
SellTicketThread sellTicketThread02 = new SellTicketThread();
SellTicketThread sellTicketThread03 = new SellTicketThread();
sellTicketThread01.start();
sellTicketThread02.start();
sellTicketThread03.start();
// SellTicketIm sellTicketIm = new SellTicketIm();
// new Thread(sellTicketIm).start();
// new Thread(sellTicketIm).start();
// new Thread(sellTicketIm).start();
}
}
class SellTicketThread extends Thread{
//继承Thread类的方式售票。
//因为每次都是新创建实例开启线程(创建多个实例对象)。要将售卖方法,
// 还有对应变量都要置为静态变量(这样方法和类变量就不受创建实例的数量影响。归类元信息所有)。以供多个线程共享资源。
public static int num = 300;
public static boolean loop = true;

private static synchronized void sell(){
    try {
        Thread.sleep(50);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    if (num<=0){
        loop = false;
        System.out.println("票卖完了");
        return;
    }
    System.out.println("窗口"+Thread.currentThread().getName()+"售卖了一张票,当前窗口余票为"+(--num));
}

@Override
 public  void run() {
    while (loop){
        sell();
    }
}

}
class SellTicketIm implements Runnable{
//实现Runnable接口的方式售票。
//实例只创建一次。交由多个线程来跑。这个实例就相当于共享资源,所以不需要将内部变量和方法置为静态类型。
// 只需将售卖方法用synchronized修饰。保证该方法同一时刻只有一个线程可以访问,其他线程为等待状态。
public int num = 1000;
public boolean loop = true;
private synchronized void sell(){
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (num<=0){
loop = false;
System.out.println(“票卖完了”);
return;
}
System.out.println(“窗口”+Thread.currentThread().getName()+“售卖了一张票,当前窗口余票为”+(–num));
}
@Override
public void run() {
while (loop){
sell();
}
}
}
线程常用方法
setName()//使线程名字与传入参数相同
getName()//获取线程名称
sleep()//使当前线程休眠给定毫秒时间。(暂停执行)
start()//使该线程开始执行(准确的说是获得可运行状态。等待cpu调度)。底层jvm调用start0()
run()//调用线程对象run方法
setPriority()//设置线程优先级
getPriority()//获取线程优先级
interrupt()//线程中断
互斥锁
线程之间的争抢只能是同一个引用,如果都是独立的引用则会产生无效的争抢。使用synchronzied修饰代码块或者类进行线程互斥。
实现互斥锁的步骤

  1. 分析需要上锁的代码
  2. 选择同步代码块或者同步方法。
  3. 保证多线程锁对象为同一个即可。即synchronzied(a)。a为多个线程共享资源即可。
  4. 采用继承Thread类和实现Runnable接口来保证互斥锁的方式不同。(尽量选择同步代码块来保证互斥。)
    ○ 继承Thread类开启线程要实例化三个实体。每个实体都有自己的属性。最好是把私有属性都用static修饰。
    ○ 实现Runnable接口只需要中需要synchronzied()修饰的同步代码或者同步方法的位置即可。因为只需要实例化一个实体。非静态同步方法的锁可以是this。也可以是其他对象(要求为同一对象)。静态同步方法的锁是当前类的Class对象。
    代码示例
    [ ] 继承Thread类非静态代码块
    public class SellThread {
    public static void main(String[] args) {
    SellTicketThread sellTicketThread01 = new SellTicketThread();
    SellTicketThread sellTicketThread02 = new SellTicketThread();
    SellTicketThread sellTicketThread03 = new SellTicketThread();
    sellTicketThread01.start();
    sellTicketThread02.start();
    sellTicketThread03.start();

// SellTicketIm sellTicketIm = new SellTicketIm();
// new Thread(sellTicketIm).start();
// new Thread(sellTicketIm).start();
// new Thread(sellTicketIm).start();
}
}
class SellTicketThread extends Thread{
//继承Thread类的方式售票。
//因为每次都是新创建实例开启线程(创建多个实例对象)。要将售卖方法,
// 还有对应变量最好置为静态变量(这样方法和类变量就不受创建实例的数量影响。归类元信息所有)。以供多个线程共享资源。
public static int num = 100;
public static boolean loop = true;

private void sell(){
    //这里如果用this则会出现超卖或重复卖现象。synchronized修饰静态代码块
    //使用SellTicketThread.class是为了获取类元信息。使多个线程共享这一个资源。进行锁竞争。形成互斥锁。
    synchronized(SellTicketThread.class){
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (num<=0){
            loop = false;
            System.out.println("票卖完了");
            return;
        }
        System.out.println("窗口"+Thread.currentThread().getName()+"售卖了一张票,当前窗口余票为"+(--num));
    }

}

@Override
 public  void run() {
    while (loop){
        sell();
    }
}

}
[ ] 继承Thread类非静态方法(普通方法)
public class SellThread {
public static void main(String[] args) {
SellTicketThread sellTicketThread01 = new SellTicketThread();
SellTicketThread sellTicketThread02 = new SellTicketThread();
SellTicketThread sellTicketThread03 = new SellTicketThread();
sellTicketThread01.start();
sellTicketThread02.start();
sellTicketThread03.start();

// SellTicketIm sellTicketIm = new SellTicketIm();
// new Thread(sellTicketIm).start();
// new Thread(sellTicketIm).start();
// new Thread(sellTicketIm).start();
}
}
class SellTicketThread extends Thread{
//继承Thread类的方式售票。
//因为每次都是新创建实例开启线程(创建多个实例对象)。要将售卖方法,
// 还有对应变量都要置为静态变量(这样方法和类变量就不受创建实例的数量影响。归类元信息所有)。以供多个线程共享资源。
public static int num = 100;
public static boolean loop = true;

private synchronized void sell(){
    //synchronized修饰普通方法
    //使用SellTicketThread.class是为了获取类元信息。使多个线程共享这一个资源。进行锁竞争。形成互斥锁。

// synchronized(SellTicketThread.class){
//
// }
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (num<=0){
loop = false;
System.out.println(“票卖完了”);
return;
}
System.out.println(“窗口”+Thread.currentThread().getName()+“售卖了一张票,当前窗口余票为”+(–num));

}

@Override
 public  void run() {
    while (loop){
        sell();
    }
}

}
[ ] 静态方法
public class SellThread {
public static void main(String[] args) {
// SellTicketThread sellTicketThread01 = new SellTicketThread();
// SellTicketThread sellTicketThread02 = new SellTicketThread();
// SellTicketThread sellTicketThread03 = new SellTicketThread();
// sellTicketThread01.start();
// sellTicketThread02.start();
// sellTicketThread03.start();

    SellTicketIm sellTicketIm = new SellTicketIm();
    new Thread(sellTicketIm).start();
    new Thread(sellTicketIm).start();
    new Thread(sellTicketIm).start();
}

}
class SellTicketIm implements Runnable{
//实现Runnable接口的方式售票。
//实例只创建一次。交由多个线程来跑。这个实例就相当于共享资源,所以不需要将内部变量和方法置为静态类型。
// 只需将sell()用synchronized修饰。保证该方法同一时刻只有一个线程可以访问,其他线程为等待状态。
public int num = 100;
public boolean loop = true;
private synchronized static void sell(){
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (num<=0){
loop = false;
System.out.println(“票卖完了”);
return;
}
System.out.println(“窗口”+Thread.currentThread().getName()+“售卖了一张票,当前窗口余票为”+(–num));
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值