java多线程

线程是通过CPU的不断的切换来执行的,不同的线程之间是交叉进行的。

**创建多线程的方式一(通过继承Thread的方式)**
/*
 * 创建一个多线程实现1-100的数字打印
 */

//创建一个子线程,创建一个线程首先要继承与Thread类
class subThread extends Thread {
    // 需要重写Tread中的run方法,run方法中是要实现的操作
    public void run() {
    for (int i = 0; i <= 100; i++) {
        System.out.println(Thread.currentThread().getName() + ": " + i);
    }
    }
}

public class Test1 {
    //创建主线程
    public static void main(String[] args) {
    //首先应该创建一个子线程的一个实例
    subThread st = new subThread();
    //通过start方法来:启动线程,并且运行线程的run方法
    //一个线程只能启动一次,不可以连续启动多次
    st.start();
    //定义一个主线程中运行的方法
    for (int i = 0; i <= 100; i++) {
        System.out.println(Thread.currentThread().getName() + ": " + i);
    }

    }

}
**创建多线程的方式二 (通过实现了Runnable接口的方式)**
//通过实现runnable接口的方式创建多线程
//1.创建一个实现了Runnable接口的类
class thread implements Runnable {
    // 重写run方法,将要执行的代码放在run方法中
    public void run() {
    for (int i = 0; i <= 100; i++) {
        System.out.println(Thread.currentThread().getName() + ": " + i);
    }

    }
}

public class test3 {
    public static void main(String[] args) {
    // 将实现了Runnable接口的类实例化,将其作为形参
    thread t = new thread();
    // 创建线程,并将上面的形参传递进去
    Thread T1 = new Thread(t);
    Thread T2 = new Thread(t);
    // 启动一个线程,注意: 线程只能有start()来启动。
    T1.start();
    T2.start();

    }

}
**两种方式的对比**
实现的方式优于继承的方式:
    1.实现的方式避免了单继承的局限性。
    2.可以处理多个线程共用一份数据。使用实现的方式更方便。

线程的安全问题:
线程的安全问题的原因是: 由于一个线程在操作共享数据时,未执行完毕的情况下,别的线程参与进来,导致数据出现安全问题。
如何解决:
方式一:同步代码块
synchronized(同步监视器){
用到了共享数据的代码块
}
其中的同步监视器就充当一个锁的标志,同步监视器可以用任意的类来充当。但是这个类也必须是所有的线程所共用的。也就是说这个锁只能是同一个对象。在通过实现Runnable接口创建的线程中可以用this来充当锁。
方式二:同步方法
将操作共享数据的方法声明为synchronized,即此方法为同步方法,能保证一个线程执行此方法时,其他线程等待其执行完毕。
同步方法的锁不需要显示的声明,默认为this.
死锁的问题:
处理线程同步问题是容易出现线程的死锁的问题。
不同的线程分别调用对方需要的同步资源不放弃,都在等待对方放弃资源,程序处于等待的状态,出现线程的死锁的问题。
写代码时,要避免死锁的出现。
线程的通信:
通过线程的通信可以控制线程的执行的顺序:
wait() : 令当前的线程挂起并释放cpu,同步资源,使别的线程可以访问并修改共享资源,而当前的线程排队等待再次对资源的访问。
notify(): 唤醒正在排队等待共享资源中优先级最高者结束等待。
notifyAll(): 唤醒正在排队等待资源的所有的线程。
以上的三种方法只能在有synchronized方法和synchronized代码块中才能使用。

package thread;
/*
 * 通过线程的通信实现甲和乙交替打印100
 */

class printNum implements Runnable {
    int num = 0;

    public void run() {
    while (true) {
        synchronized (this) {
        notify(); // 唤醒正在排队的优先级最高的线程
        if (num <= 100) {
            System.out.println(Thread.currentThread().getName() + ":" + num);
            num++;
            try {
            wait(); // 让当前的线程进入等待的队列
            } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }
        } else {
            break;
        }
        }
    }
    }
}

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

    printNum p = new printNum();
    Thread t1 = new Thread(p);
    Thread t2 = new Thread(p);
    t1.setName("甲");
    t2.setName("乙");
    t1.start();
    t2.start();

    }

}

Tread的常用的方法:
1.start(): 启动线程并执行相应的run()方法
2.run(): 子线程的执行代码放在run()方法中
3.currentTread(): 静态的,调取当前的线程,返回的是thread类
4.getName(): 获取此线程的名字
5.setName(string ) : 设置此线程的名字
6.yield(): 调用当前的线程释放当前的cpu的执行权
7.join(): 在A线程中调用B线程的join()方法,表示:当执行到此方法时A 线程停止执行,直到B线程执行完毕继续执行A线程。
8.isAlive():判断当前的线程是否还存活
9.sleep(long L):显示的让当前的线程睡眠L毫秒。
Thread的优先级:(优先级越高只是抢占到cpu权限的概率变大了,具体的执行情况还是不确定的)
线程的优先级一共有10级,从1到10逐级增大。
MAX_PRIORITY :表示最大的优先级10级
MIN_PRIORITY : 表示最小的优先级1级
NORM_PRIORITY : 表示默认的优先级5级
优先级的方法:
getPriority(): 返回的线程的优先级
setPriority(int newPriority): 改变线程的优先级

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值