java中的多线程问题

1.什么是进程,线程,多线程

进程是系统中正在运行的程序
线程是进程的执行单元,执行路径
多线程是多个线程并发执行的技术.

2.什么情况下使用多线程:

(1).单线程不能满足业务需要.比如火车票售票系统,在同一时间可能有多个请求,这些请求之间是相互独立的,没有依赖关系,后台必须通过多线程保证对用户的及时响应.
(2).单线程不能满足性能要求,通过多线程提高效率.比如,多线程可以用一个线程专门用于读写文件,其他的线程用于对读取数据进行处理,这样才有可能更好地利用 CPU 资源。

3.什么是线程安全

  
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码,如果每次运行结果和单线程运行的结果是一样的,那就是线程安全的。如果运行结果和单线程的运行结果不同,就为线程不安全.

4.多线程的两种实现方式

(1)继承Thread,重写run()方法

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int x = 0; x < 100; x++) {
                System.out.println(getName()+ x);
        }
    }
}

(2)实现Runnable,重写run()方法

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int x = 0; x < 100; x++) {
        // getName()方法是Thread类的,而MyRunnable只实现了
        Runnable接口,本身没有getName(),所以不能使用。
                                                   System.out.println(Thread.currentThread().getName()
                                 + "---hello"+ x);
                }
            }

}
一般使用第二种方式,因为方式一只能单继承,有一定的局限性,而方式二只创建一个对象,实现了数据和操作更好的分离.

5.通过火车票案例了解多线程(四个窗口同时出售火车票)

public class TicketRunnable implements Runnable {

private static int tickets = 100;

@Override
public void run() {
    while (true) {
        //通过加锁,保证线程安全
        synchronized (this) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()
                            + "正在出售第" + (tickets--) + "张票");
                }
                else {
                    break;
                }
        }
    }
}
}

主函数

public class RunnableTest {
public static void main(String[] args) {

    TicketRunnable tr = new TicketRunnable();

    Thread t1 = new Thread(tr,"窗口1");
    Thread t2 = new Thread(tr,"窗口2");
    Thread t3 = new Thread(tr,"窗口3");
    Thread t4 = new Thread(tr,"窗口4");

    t1.start();
    t2.start();
    t3.start();
    t4.start();
}
}
注:(1).多线程中的锁对象可以为任意对象,但必须为同一对象
    静态方法锁对象:是当前类的字节码文件对象   类名.class 
(2).解决线程同步问题的两种方式
    a、同步代码块
    synchronized(锁对象) {....}    //锁对象可以是任意类型
    b、同步方法
    格式:public synchronized 返回值 方法名(){....}
    锁对象:this
(3)如何判断线程是否安全
     a、看有没有共享数据
     b、看操作共享数据的语句是不是多条语句
     c、看是不是在多线程的环境中

6.线程死锁问题

public class DieLock extends Thread {

private boolean flag;
public DieLock(boolean flag) {
    this.flag = flag;
}

@Override
public void run() {
    if (flag) {
        synchronized (MyLock.objA) { 
            System.out.println("true -- objA");
            synchronized (MyLock.objB) {
                System.out.println("true -- objB");
            }
        }
    } else {
        synchronized (MyLock.objB) {
            System.out.println("false -- objB");
            synchronized (MyLock.objA) {
                System.out.println("false -- objA");
            }
        }
    }
}
}
死锁原因总结
     线程1自身拿着一个锁:A锁,线程2自身拿着一个锁:B锁
     当线程1要用B锁,线程B要用A锁的时候就会发生死锁
如何避免死锁:
    不嵌套使用锁

7.线程的优先级

1、线程优先级级别
 线程默认优先级是5。范围是1-10
 Thread.MAX_PRIORITY         //10
 Thread.MIN_PRIORITY         //1
 Thread.NORM_PRIORITY     //5

2、方法
 public final int getPriority():获取线程优先级
 public final void setPriority(int newPriority):更改线程的优先级

3、注意
 优先级可以在一定的程度上,让线程获较多的执行机会

4、举例
 MyThread t = new MyThread();
 System.out.println(t.getPriority());
 t.setPriority(Thread.MAX_PRIORITY);

8.线程的等待唤醒机制

(1).前提: 两个线程共用一把锁,此时可以调用该锁的wait和notify方法,实现等待唤醒机制
(2)sleep和wait的区别
wait:是Object类的方法,可以不用传递参数,释放锁对象
sleep:是Thread类的静态方法,需要传递参数
案例:多线程实现设置和获取学生信息
Student类

public class Student {
private String name;
private int age;
private boolean flag = false;

public synchronized void set(String name, int age) {
    // 如果有数据就等待
    if (this.flag) {
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 设置值
    this.name = name;
    this.age = age;

    // 修改标记
    this.flag = true;
    this.notify();
}

public synchronized void get() {
    // 如果没有数据就等待
    if (!this.flag) {
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 获取值
    System.out.println(this.name + "***" + this.age);

    // 修改标记
    this.flag = false;
    this.notify();
}
}

SetStudent类

public class SetStudent implements Runnable {
private Student s;

public SetStudent(Student s) {
    this.s = s;
}

@Override
public void run() {
    int x = 0;
    while (true) {
        if (x % 2 == 0) {
            s.set("林青霞", 26);
        } else {
            s.set("刘意", 29);
        }
        x++;
    }
}
}

GetStudent类

public class GetStudent implements Runnable {
private Student s;

public GetStudent(Student s) {
    this.s = s;
}

@Override
public void run() {
    while (true) {
        s.get();
    }
}
}

StudentTest测试类

public class StudentTest {
public static void main(String[] args) {
    Student s = new Student();// 资源类

    SetStudent ss = new SetStudent(s);
    GetStudent gs = new GetStudent(s);

    Thread t1 = new Thread(ss);
    Thread t2 = new Thread(gs);

    t1.start();
    t2.start();
}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值