Java多线程与并发(一)之概念及操作方法

进程和线程的概念

进程:一个具有独立内存空间的执行程序
线程:是进程中的其中一条执行路径(多条就是多线程),每个进程最少有一个进程 同一个进程中的多个线程共享同一个内存空间

我们Windows中任务管理器中的就是进程
这里写图片描述
线程, 如图所示, 在进程中可能包含多个线程,也可以说是多条执行路径, 每个线程之间还可能会有交叉(数据的沟通)
这里写图片描述

网上有个典型的例子可以跟大家分享一下:
进程与线程的一个简单解释

实现多线程的两种方式

1,继承Thread类
2,实现Runable接口(推荐使用)

接下类针对两种方法进行详细阐述:

继承Thread类方法:
步骤: 1, 当然是继承Thread类 2, 重写run()方法

    // 继承Thread类实现线程
    static class MyThread extends Thread {
        @Override
        public void run() {
            // 在此方法中编写线程要执行的工作
        }
    }

实现Runable接口(推荐使用):
步骤: 1, 实现Runable方法 2, 同样重写run() 方法
推荐原因: 由于Java不支持继承多个父类,但是可以实现多个接口, 如果直接继承Thread类, 在后续开发过程中就没有继承其他类的机会了!所以推荐使用实现Runnable接口

    // 实现Runable接口的方式实现线程 推荐使用
    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            // 在此方法中编写线程要执行的工作
        }
    }

常用的几个操作方法

  • Thread(Runnable target) 分配新的 Thread 对象。这种构造方法与 Thread(null, target,gname) 具有相同的作用,其中的 gname 是一个新生成的名称。自动生成的名称的形式为 “Thread-”+n,其中的 n 为整数。
  • start()使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
    结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。 多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
  • getId() 返回该线程的标识符。
  • getName() ,setName(String name) 线程名称的get和set方法
  • getPriority() ,setPriority(int newPriority) 优先级的get和set方法
  • currentThread() 返回对当前正在执行的线程对象的引用。
  • isAlive() 测试线程是否处于活动状态。
  • join(), join(long millis) 等待该线程终止。
  • yield() 暂停当前正在执行的线程对象,并执行其他线程。
  • setDaemon(boolean on) 将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。

  • sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。也就是说线程执行sleep方法时不会让出自己锁, 要注意和Object中wait() 方法差异,在后面会有阐述

    以上部分方法的示例代码如下:

package com.lulu;
public class ThreadDemo1 {

    public static void main(String[] args) {

        // 分配新的 Thread 对象。
        Thread t1 = new Thread(new MyRunnable());

        System.out.println("isAlive-->" + t1.isAlive());
        // 启动该线程
        t1.start();// 线程已准备就绪(就绪状态)等待CPU的调度
        System.out.println("isAlive-->" + t1.isAlive());
        // 很少用到getId()方法
        System.out.println("Id-->" + t1.getId());
        System.out.println("Name-->" + t1.getName());
        // 设置抢占CPU执行时间的优先级
        // t.setPriority(Thread.MAX_PRIORITY);// 只是几率大但不保证每次抢占成功

        MyThread t2 = new MyThread();
        t2.start();

        // 使用Main方法中的线程演示Join方法
        for (int i = 0; i < 5; i++) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // Thread.currentThread():返回对当前正在执行的线程对象的引用。
            System.out.println(Thread.currentThread().getName() + "->" + i);
            if (i == 2) {
                try {

                    // 此处的含义是, 当i==2时等待t1执行完再执行自己的线程
                    t1.join();
                    // 如果t1线程异常中断了,会抛出下面的异常
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }

    }

    static class MyThread extends Thread {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
            for (int i = 0; i < 5; i++) {

                try {
                    // Causes the currently executing thread to sleep
                    // (temporarily cease execution) for the specified number of
                    // milliseconds, subject to the precision and accuracy of
                    // system timers and schedulers. The thread does not lose
                    // ownership of any monitors.
                    // 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),
                    // 此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                // Thread.currentThread():返回对当前正在执行的线程对象的引用。
                System.out.println(Thread.currentThread().getName() + "->" + i);

            }

        }
    }

    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // Thread.currentThread():返回对当前正在执行的线程对象的引用。
                System.out.println(Thread.currentThread().getName() + "->" + i);

            }
        }
    }

}

程序运行结果:
这里写图片描述

对于线程各方法的执行过程可以参考下图:

这里写图片描述
上图中部分方法会在后续博客中给出说明.

未完待续….

以上纯属个人见解, 如有不足之处希望有高人指出, 定感激不尽, 如有喜欢交流学习经验请给我留言谢谢.

原创文章, 转载请注明出处

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值