并行随笔(1)

来源:互联网 发布:csi接口 数据通信协议 编辑:程序博客网 时间:2024/05/19 23:58

线程和进程的关系

在早期的面向进程的计算机结构之中,进程是程序执行的基本实体,在现代面向线程的计算机结构之中进程是线程的容器。程序是指令,数据及其组织形式的描述,进程是程序的实体。线程是轻量级的进程,是程序执行的最小单位。使用多线程而不使用多进程,是应为线程之间的切换和调度成本远小于进程。

java.lang.Thread包。

  1. Thread.State 线程的状态:
public enum State {         NEW,//表示刚刚创建,但是还没有开始执行,等待start()方法调用        RUNNALE,//当线程执行的时候,,表示线程一切的资源都已经准备好了        BLOCKED,//当线程在执行的时候遇到了synchronized同步代码块,进入到blocked(阻塞)状态直到获得请求的锁        WAITING,//无限期地等待另一个线程来执行某一特定操作的线程处于这种状态。        TIME_WAITING,//等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。         TERMINATED//当线程执行完毕之后        }

  • 新建线程的两种方式:
public class Demo {    public static void main(String[] args) {        Thread t1 = new Thread() {            @Override            public void run() {                System.out.println("这是线程1");            }        };        t1.start();        System.out.println("线程1的id:" + t1.getId());        System.out.println("主线程id:" + Thread.currentThread().getId());        Thread t2 = new Thread(new Thread2());        t2.start();    }}class Thread2 implements Runnable {    @Override    public void run() {        System.out.println("这是线程2");    }}

这里我们通过两种方式来新建了两个线程,一种是直接new
一种是通过实现Runnable接口。那么这两种方式有什么区别那?
看一下源码

public interface Runnable {   public abstract void run();}可以看出Runnable 中只有一个run方法。而Thread中有一个十分重要的构造:public Thread(Runnable target)在我们start()这个线程的时候会默认之心Thread.run()。而run()方法  public void run() {        if (target != null) {            target.run();        }    }会先判断一下。这样我们就避免了单继承的局限性。通常使用第二种方法来新建一个线程

终止线程

Thread提供了一个stop()方法来终止线程但是他已经过时了不推荐使用。因为他太过于暴力,强行停止线程会造成对临界区
(共享资源)数据不一致的问题。执行以下代码:
我们应该得到的age和name都是一致的。然而。。。

package Test1;public class Demo2 {    public static User u = new User();    public static class User {        private String name;        private int age;        public User() {            name = "0";            age = 0;        }        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }        public int getAge() {            return age;        }        public void setAge(int age) {            this.age = age;        }        @Override        public String toString() {            return "User [name=" + name + ", age=" + age + "]";        }    }    public static class ChangeUserThread implements Runnable {        @Override        public void run() {            while (true)                synchronized (u) {                    int v = (int) (System.currentTimeMillis() / 1000);                    u.setAge(v);                    try {                        Thread.sleep(100);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    u.setName(String.valueOf(v));                }        }    }    public static class ReadUserThread implements Runnable {        @Override        public void run() {            while (true)                synchronized (u) {                    if (u.getAge() != Integer.parseInt(u.getName()))                        System.out.println(u);                }        }    }    public static void main(String[] args) throws InterruptedException {        new Thread(new ReadUserThread()).start();        while (true) {            Thread t = new Thread(new ChangeUserThread());            t.start();            Thread.sleep(200);            t.stop();        }    }}

这里写图片描述

虽然我们加了锁但是还是导致读取数据不一致。那该如何终止线程那?很简单,我们设置一个标记用于指示当前线程是否退出。

public static class ChangeUserThread implements Runnable {        volatile boolean stopflag = false;        public void stopFlag() {            this.stopflag = true;        }        @Override        public void run() {            while (true) {                if (stopflag) {                    System.out.println("停止");                    break;                }
0 0