java 线程创建的方法

这几天开始学习java并发编程实战,发现这本书理论知识很多,实践并不多,而且基本知识貌似默认大家是知道的。所以边看边学习一下基础知识。

1.首先看下官方API文档的介绍:
  • JVM允许在一个程序中同时有多个运行的线程。
  • 每个线程都有一个优先级(priority),优先级高的线程运行时要优先于优先级低的线程,每个线程要么是守护线程,要么不是。当一个线程在运行时创建另一个线程是,新线程最初的优先级和创建它的线程一样。一个线程是守护线程当且仅当创建它的线程是守护线程。
    -创建线程有两种方法,一种是继承Thread类并实现Run()方法,另一种是实现Runnable接口并实现run方法。
2.第一种方法:继承Thread类并实现run方法
public class MyThread extends Thread {
    //可以指定线程的名字
    public MyThread(String threadName){ super(threadName); }
    public void run() {
        for(int i = 0; i < 5; i++) {
        System.out.println(Thread.currentThread().getName() + " " + i);
        //请求让出对CPU的占用,即主动请求切换线程,但是实际切换不切换要看CPU心情
        Thread.yield();
    }
    }
    public static void main(String[] agrs) {
    new MyThread("thread 1").start();
    new MyThread("thread 2").start();
    new Thread().start();
   }
}
result:
thread 2 0
thread 1 0
thread 2 1
thread 1 1
thread 2 2
thread 1 2
thread 2 3
thread 1 3
thread 2 4
thread 1 4

这里main方法中最后的线程就是Thread类本身而不是它的子类,虽然文档上讲需要实现Run方法,但Run方法Thread实现Runnable方法后必须实现的,并不是abstract方法,不实现也不会报错,但是不实现的话这个线程其实啥都不会做,因为Run方法是空的。
因为main中两个线程的优先级是相同的,所以执行顺序并不确定,每次运行的结果都是随机的。
Thread类的构造器有:
Thread()
Thread(Runnable target) //指定Runnable,与后面第二种方法有关
Thread(String name) //指定线程的名称
Thread(Runnable target, String name)
Thread(ThreadGroup group, Runnable target) //指定线程组
Thread(ThreadGroup group, String name)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)

3.第二种方法:实现Runable接口,并实现run方法
class MyThread implements Runnable {
    public void run() {
        for(int i = 0; i < 5; i++) {
        System.out.println(Thread.currentThread().getName() + " " + i);
        Thread.yield();
        }
    }
    public static void main(String[] args) {
        new Thread(new MyThread(),"thread 1").start();
        new Thread(new MyThread(),"thread 2").start();
    }
}
result:
thread 2 0
thread 1 0
thread 1 1
thread 1 2
thread 1 3
thread 1 4
thread 2 1
thread 2 2
thread 2 3
thread 2 4

在这里因为是实现接口,所以就必须实现Run()方法了。

4.特别方法:匿名内部类
public class MyThread {
    public static int num = 1;
    public static void getNum() { 
        for(int i = 0; i < 5; i++){
            System.out.println(Thread.currentThread().getName() + " " + num++);
            Thread.yield();
        }
    }
    public static void main(String[] args){
        Thread thread1 = new Thread(new Runnable() { public void run() { MyThread.getNum();} },"thread1");
        Thread thread2 = new Thread(new Runnable() { public void run() { MyThread.getNum();} },"thread2");
        thread1.start();
        thread2.start();
        try {
            thread1.join();
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        try {
            thread2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(MyThread.num);
    }
}
result:
thread1 1
thread2 1
thread1 2
thread2 3
thread1 4
thread2 5
thread1 6
thread2 7
thread1 8
thread2 9
10

这里其实还是第二种方法,只不过是用匿名内部类实现。但是仔细观察输出的结果,thread 1和thread 2 都输出一个num = 1(这是程序重复运行好几次才偶尔出现的)。这个因为我的MyThread类并不是线程安全的,当都多个线程同时访问这个类的数据并且数据有更改时,可能得到错误的数据。这是下一篇线程安全的问题啦。

4.总结

其实构造线程无非就是继承和实现接口两种方法,但是具体的形式可以有很多种,比如第三种方法,但是万变不离其宗。另外,多线程编程一定和线程安全和锁是紧密联系。
Thread类的方法由于现在还不需要用到,所以以后在总结。官方API文档对方法介绍的都很好,比如虽然有destroy方法,但是这个方法在现实编程中不能使用,因为他会产生线程死锁等危害。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值