Java学习随记之多线程编程

Process和Thread

程序是指令和数据的有序集合, 本身没有运行的含义,是一个静态的概念。

进程是执行程序的一次执行过程,他是一个动态的概念,是系统资源分配的单位

一个进程中可以包含若干个线程,线程是CPU调度和执行的单位

线程创建

三种创建方法

继承Thread类

//创建线程方法一:继承Thread类,重写run() 方法,调用start开启主线程
public class TestThread01 extends Thread{
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 2000; i++) {
            System.out.println("我在看代码-----" + i);
        }
    }
    public static void main(String[] args) {
        //main线程,主线程
        //创建一个线程对象
        TestThread01 testThread01 = new TestThread01();
        //调用start方法开启多线程,子线程调用run方法,主线程和子线程并行交替执行
        testThread01.start();
        //testThread01.run(); //主线程调用run方法,只有主线程一条执行路径

        for (int i = 0; i < 2000; i++) {
            System.out.println("Im" + i);
        }
    }
}

总结:注意,线程开启不一定立即执行,由CPU调度处理

  • 子类继承Thread类,具备多线程能力、
  • 启动线程:子类对象.start()
  • 不推荐使用:避免OOP单继承局限性

小练习

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;

//练习Thread,实现多线程同步下载图片
public class TestThread02 extends Thread{
    private String url;
    private String name;

    public TestThread02(String url, String name) {
        this.url = url;
        this.name = name;
    }
    @Override
    public void run() {
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloadr(url, name);
        System.out.println("下载了:" + name);

    }

    public static void main(String[] args) {
        TestThread02 t1 = new TestThread02("https://img-blog.csdnimg.cn/20201130170256201.png?…3dlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "1.png");
        TestThread02 t2 = new TestThread02("https://img-blog.csdnimg.cn/20201130170221843.png", "2.png");
        TestThread02 t3 = new TestThread02("https://img-blog.csdnimg.cn/20201130170256201.png?…3dlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "3.png");

        t1.start();
        t2.start();
        t3.start();
    }
}
//下载器
class WebDownloader{
    public void downloadr(String url, String name){
        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常, downloader出现问题");
        }
    }
}

实现Runnable

//创建线程方式二:实现Runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
public class TestThread03 implements Runnable{
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 2000; i++) {
            System.out.println("我在看代码-----" + i);
        }
    }

    public static void main(String[] args) {
        //创建runnable 接口的实现类对象
        TestThread03 testThread03 = new TestThread03();

        //创建线程对象,通过线程对象来开启线程,代理
//        Thread thread = new Thread(testThread03);
//        thread.start();
        new Thread(testThread03).start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("Im" + i);
        }
    }
}

总结:

  • 实现接口Runnable具备多线程能力
  • 启动线程:传入目标对象+Thread对象.start()
  • 推荐使用:避免单继承局限性,灵活方便,方便同一个对象被线程使用

出现的问题

多个线程操作操作同一个资源的情况下,线程不安全,数据紊乱

//多个线程同时操作同一个对象
//买火车票的例子

//发现问题:多个线程操作操作同一个资源的情况下,线程不安全,数据紊乱
public class TestThread04 implements Runnable {

    //票数
    private int ticketNums = 10;

    @Override
    public void run() {
        while (true) {
            if (ticketNums <= 0) {
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "拿到了第" + ticketNums-- + "票");
        }
    }

    public static void main(String[] args) {
        TestThread04 testThread04 = new TestThread04();

        new Thread(testThread04, "老师").start();
        new Thread(testThread04, "黄牛").start();
        new Thread(testThread04, "小明").start();
    }
}

实现Callable接口

1、实现Callable接口,需要返回值类型

2、重写call方法,需要抛出异常

3、创建目标对象

4、创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(3);(使用了线程池)

5、提交执行:Future r1 = ser.submit(t1);

6、获取结果:boolean res1 = r1.get();

7、关闭服务:ser.shutdown();

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;

//线程创建方式三:实现Callable接口(了解即可)
// 实现Callable接口
public class TestCallable implements Callable<Boolean> {

    private String url;
    private String name;

    public TestCallable(String url, String name) {
        this.url = url;
        this.name = name;
    }
    @Override
    public Boolean call() {
        WebDownloader1 webDownloader1 = new WebDownloader1();
        webDownloader1.downloadr(url, name);
        System.out.println("下载了:" + name);
        return true;

    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable t1 = new TestCallable("https://img-blog.csdnimg.cn/20201130170256201.png?…3dlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "1.png");
        TestCallable t2 = new TestCallable("https://img-blog.csdnimg.cn/20201130170221843.png", "2.png");
        TestCallable t3 = new TestCallable("https://img-blog.csdnimg.cn/20201130170256201.png?…3dlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "3.png");

        //1、创建执行服务()    线程池
        ExecutorService ser = Executors.newFixedThreadPool(3);
        //2、提交执行
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);
        Future<Boolean> r3 = ser.submit(t3);

        //3、获取结果
        boolean res1 = r1.get();
        boolean res2 = r2.get();
        boolean res3 = r3.get();

        //4、关闭服务
        ser.shutdown();

    }

}
//下载器
class WebDownloader1{
    public void downloadr(String url, String name){
        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常, downloader出现问题");
        }
    }
}

Lambda表达式

为什么要使用lamba表达式

避免匿名内部类定义过多

可以让代码看起来更整洁

去掉了一堆没有意义的代码,只留下核心逻辑

示例

/**
 * 推导lambda表达式
 */

public class TestLambda01 {

    //3、静态内部类
    static class Like2 implements ILike {

        @Override
        public void lambda() {
            System.out.println("I like lambda2");
        }
    }

    public static void main(String[] args) {
        ILike like = new Like();
        like.lambda();

        like = new Like2();
        like.lambda();

        //4、局部内部类
        class Like3 implements ILike {
            @Override
            public void lambda() {
                System.out.println("I like lambda3");
            }
        }
        like = new Like3();
        like.lambda();

        //5、匿名内部类
        like = new ILike() {
            @Override
            public void lambda() {
                System.out.println("I like lambda4");
            }
        };
        like.lambda();

        //6、用lambda简化 jdk1.8特性
        like = ()->{
            System.out.println("I like lambda5");
        };
        like.lambda();

    }
}

//1、定义一个函数式接口----必须有
interface ILike {
    void lambda();
}

//2、实现类
class Like implements ILike {

    @Override
    public void lambda() {
        System.out.println("I like lambda");
    }
}

对于lambda表达式的简化

public class TestLambda02 {

    public static void main(String[] args) {
        //标准格式
//        ILove love = (int a)->{
//                System.out.println("I Love you " + a);
//        };
        //简化1   去掉参数类型,多个不同类型的参数也可以直接去掉
        ILove love = (a) -> {
            System.out.println("I love you " + a);
        };
        //简化2   去掉括号    -->仅单参数
        love = a->{
            System.out.println("I love you " + a);
        };
        //简化3   去掉花括号  --> 仅lambda表达式有一行时才可
        love = a -> System.out.println("I love you " + a);
        love.love(520);
        //使用lambda表达式仅适用于函数式接口(接口里只有一个函数接口)
    }
}

interface ILove {
    void love(int a);
}

静态代理

//静态代理模式:
//真实对象和代理对象都要实现同一个接口
//代理对象要代理真实角色
//好处:
    //代理对象可以做很多真实对象做不了的事
    //真实对象专注做自己的事
public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();

        new Thread(	() -> System.out.println("I Love You")).start();
        new WeddingCompany(new You()). HappyMarry();

    }
}

interface Marry {
    void HappyMarry();

}
// 真实对象
class You implements Marry {
    @Override
    public void HappyMarry() {
        System.out.println("Happy");
    }
}

// 代理
class WeddingCompany implements Marry {
    //代理谁->真实目标角色
    private Marry target;

    public WeddingCompany(Marry target) {
        this.target = target;
    }

    @Override
    public void HappyMarry() {
        before();
        this.target.HappyMarry();
        after();
    }

    private void after() {
        System.out.println("后");
    }

    private void before() {
        System.out.println("前");
    }
}

线程状态

方法 说明
setPriority(int newPriority) 更改线程的优先级
static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠
void join() 等待该线程终止
static void yield() 暂停当前正在执行的线程对象,并执行其他线程
void interrupt() 中断线程,别用这个方式
boolean isAlive() 测试线程是否处于某个活动状态

线程终止

  • 不推荐使用JDK提供的stop()、destroy()方法
  • 推荐线程自己停止下来
  • 建议使用一个标志位进行终止变量,当flag = false,则终止线程运行
//测试stop
//1、建议线程正常停止---->利用次数,不建议死循环
//2、建议使用标志位----->设置一个标志位
//3、不要使用stop或者destroy等过时或者jdk不推荐的方法
public class TestStop implements Runnable {
    //1、设置一个标志位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("run-----thread" + i++);
        }
    }
    //2、设置一个公开的方法停止线程,转换标志位
    public void stop() {
        this.flag = false;
    }
    public static void main(String[] args) throws InterruptedException {
        TestStop testStop = new TestStop();

        new Thread(testStop).start();

        for (int i = 0; i < 1000; i++) {
            Thread.sleep(1);
            if (i == 900) {
                testStop.stop();

                System.out.println("Stop");
                break;
            }
        }
    }
}

线程休眠

  • sleep(时间) 指定当前线程阻塞的毫秒数
  • sleep存在异常InterruptedException
  • sleep时间达到后进入就绪状态
  • sleep可以模拟网络延时(放大问题的发生性),倒计时等
  • 每一个对象都有一个锁,sleep不会释放锁
import java.text.SimpleDateFormat;
import java.util.Date;

public class TestSleep2 {
    //模拟倒计时
    public static void tenDown(){
        int num = 10;
        while (num > 0) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(num--);
        }
    }

    public static void main(String[] args) {
        //打印当前时间
        Date startTime = new Date(System.currentTimeMillis());  //获取时间

        while (true) {
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:MM:SS").format(startTime));
                startTime = new Date(System.currentTimeMillis());//更新时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程礼让

  • 礼让线程,让当前正在执行的线程停止,但不阻塞
  • 让线程从运行态转换为就绪态
  • 让CPU重新进行调度,礼让不一定成功,看CPU心情
public class TestYield {
    public static void main(String[] args) {
        Myyield myyield = new Myyield();

        new Thread(myyield, "A").start();
        new Thread(myyield, "B").start();
    }
}

class Myyield implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() +  "线程开始");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() +  "线程停止");
    }
}

JOIN

JOIN合并线程,待此线程执行完后,再执行其他线程,其他线程阻塞

可以想象成插队

//插队
public class TestJoin implements Runnable{
    @Override
    public void run() {
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 100; i++) {
            System.out.println("VIP" + i);
        }
    }

    public static void main(String[] args) {
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();

        for (int i = 0; i < 1000; i++) {
            if (i == 200) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("main" + i);
        }
    }
}

线程状态观测

线程状态。线程可以处于以下状态之一:

NEW

尚未启动的线程处于此状态。

RUNNABLE

在Java虚拟机中执行的线程处于此状态。

BLOCKED

被阻塞等待监视器锁定的线程处于此状态。

WAITING

无限期等待另一个线程执行特定操作的线程处于此状态。

TIMED_WAITING

正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。

TERMINATED

已退出的线程处于此状态。

//观测测试线程的状态
public class TestStatus {

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(i);
            }
            System.out.println("/////////////");
        });

        //观察状态
        Thread.State state = thread.getState();
        System.out.println(state);

        //观察启动后
        thread.start();

        state = thread.getState();
        System.out.println(state);

        while (state != Thread.State.TERMINATED) { //只要线程不终止,就一直输出状态
            try {
                Thread.sleep(100);
                state = thread.getState();
                System.out.println(state);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }
}

线程的优先级

Java提供一个线程调度器来监控程序中启动后进入就绪态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行

线程的优先级用数字表示,范围从1~10

  • Thread.MIN_PRIORITY = 1;
  • Thread.MAX_PRIORITY = 10;
  • Thread.NORM_PRIORITY = 5;

使用以下方法改变或者获取优先级

  • getPriority
  • setPriority

优先级低只是意味着获得调度的概率低,并不是优先级低的就不会调用了,这都是看CPU的调度

public class TestPriority extends Thread {

    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + "====>" + Thread.currentThread().getPriority());

        MyPriority myPriority = new MyPriority();

        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);
        Thread t3 = new Thread(myPriority);
        Thread t4 = new Thread(myPriority);
        Thread t5 = new Thread(myPriority);

        t1.start();
        t2.setPriority(1);
        t2.start();
        t3.setPriority(4);
        t3.start();
        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();
        t5.setPriority(8);
        t5.start();
    }
}

class MyPriority implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "====>" + Thread.currentThread().getPriority());
    }
}

守护(daemon)线程

  • 线程分为用户线程和守护线程
  • JVM虚拟机必须确保用户线程执行完毕
  • JVM虚拟机不用等待守护线程执行完毕
public class TestDaemon {
    public static void main(String[] args) {
        God god = new God();
        You you = new You();

        Thread thread = new Thread(god);
        thread.setDaemon(true);//默认式false表示是用户线程,正常的线程是用户线程

        thread.start();

        new Thread(you).start();
    }

}

//上帝
class God implements Runnable {

    @Override
    public void run() {
        while (true) {
            System.out.println("god");
        }
    }
}
//你
class You implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("Happy");
        }
        System.out.println("Goodbye world");
    }
}

同步(synchronized)

synchronized

由于我们可以提出private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized方法和synchronized块。

public synchronized void method(){}

synchronized方法控制对“对象”的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行

缺陷:若将一个大的方法声明为synchronized,将会影响效率

同步方法

synchronized方法控制对成员变量或者类属性对象的访问,每个对象对应一把锁。写法如下:

public synchronized void test(){
    //。。。。
}
  1. 如果修饰的是具体对象:锁的是对象
  2. 如果修饰的是成员方法:锁的是this
  3. 如果修饰的是静态方法:锁的就是这个对象.class

每个synchronized方法都必须获得该方法的对象的锁才能执行,否则所属的这个线程阻塞,方法一旦执行,就独占该锁,直到该方法返回时,锁释放。

原程序:

public class Checkout {

    public static void main(String[] args) {
        Account account = new Account(200000, "礼金");
        Drawing you = new Drawing(account, 80000, "你");
        Drawing wife = new Drawing(account, 140000, "your wife");
        you.start();
        wife.start();
    }
}

class Account {
    int money;
    String name;

    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}

class Drawing extends Thread {
    Account account;
    int outMoney;
    int outTotal;

    public Drawing(Account account, int outMoney, String name) {
        super(name);
        this.account = account;
        this.outMoney = outMoney;
    }

    @Override
    public void run() {
        test();
    }

    public void test() {
        if (account.money < outMoney) {
            System.out.println("余额不足");
            return;
        }
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        account.money -= outMoney;
        outTotal += outMoney;
        System.out.println(this.getName() + "-----账户余额为:" + account.money);
        System.out.println(this.getName() + "-----总共取到了:" + outTotal);
    }
}

显然,上面的代码会出现负数,但是我们不希望它出现负数。

同步方法的写法代码,以上面代码为例,直接在提款机的操作,把run方法或者里面的内容提出来变成test,加上synchronized修饰:

@Override
public void run(){
}
public synchronized void test(){
}

但是这样仍会发现出现负数,锁定失败。

分析:

我们认为在test方法里进行的对象修改,所以把他锁上就好了,但是,对于这个类,这个提款机来说,test时成员方法,因此锁的对象实际上是this,也就是提款机(Drawing)。

但是我们的初衷,希望线程锁定的资源是Account对象,而不是提款机对象。

同步块

除了方法,synchronized还可以修饰块,叫做同步块。

synchronized修饰同步块的方式是:

synchonized (obj){ }

其中的obj可以是任何对象,但是用到它,肯定是设置为那个共享资源,这个obj被称为同步监视器。同步监视器的作用就是,判断这个监视器是否被锁定(是否能访问),从而决定其是否能执行其中的代码。

Java的花括号中内容有一下几种:

  1. 方法里面的块:局部快。解决变量作用域的问题,快速释放内存(比如方法里面再有个for循环,里面的变量)
  2. 类层的块:构造块。初始化信息,和构造方法是一样的
  3. 类层的静态块:静态构造块。最早加载,不是对象的信息,而是类的信息;
  4. 方法里面的同步块:监视对象。

第四种就是我们目前学习的同步块。

注意:如果是同步方法里,没必要指定同步监视器,因为同步方法的监视器已经是this或者.class

使用同步块对提款机问题进行修改:

public void test(){
    synchronized(account){

    }
}

也就是加上对account的监视器,锁住了这个对象 ,这样运行结果就正确了。

这种做法的效率不高,因为虽然对account上了锁,但是每一次都要把整个流程走一遍,方法体内的内容是很多的,另外,每次加锁与否,都是对性能的消耗,进入之后再出来,哪怕什么都不做,也是消耗。

其实,我们可以在加锁的外面再加一重判断,那么之后就没有必要再进行锁的过程了。

public void test(){
    if (account.money == 0){
        return;
    }
    synchronized(account){
    }
}

就是这样的代码,在并发量很高的时候,往往可以大大提高效率。

问题

synchronized块太小,可能锁不住,安全性又太低了,锁的方法太大,又会降低效率,所以要很注意控制范围 

以上就是Java学习随记之多线程编程的详细内容,更多关于Java多线程的资料请关注我们其它相关文章!

(0)

相关推荐

  • 什么是Java多线程,如何实现

    目录 什么是进程? 什么是线程? 什么是线程安全? 添加一个状态呢? 如何确保线程安全? synchronized lock 总结 什么是进程? 电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的.比如下图中的QQ.酷狗播放器.电脑管家等等. 什么是线程? 进程想要执行任务就需要依赖线程.换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程. 那什么是多线程?提到多线程这里要说两个概念,就是串行和并行,搞清楚这个,我们才能更好地理解多线程.

  • Java多线程基本概念以及避坑指南

    目录 前言 1. 多线程基本概念 1.1 轻量级进程 1.2 JMM 1.3 Java中常见的线程同步方式 2. 避坑指南 2.1. 线程池打爆机器 2.2. 锁要关闭 2.3. wait要包两层 2.4. 不要覆盖锁对象 2.5. 处理循环中的异常 2.6. HashMap正确用法 2.7. 线程安全的保护范围 2.8. volatile作用有限 2.9. 日期处理要小心 2.10. 不要在构造函数中启动线程 End 前言 多核的机器,现在已经非常常见了.即使是一块手机,也都配备了强劲的多核处

  • Java多线程基础

    目录 一.线程 二.创建多线程的方式 1.继承Thread类实现多线程 2.实现Runnable接口方式实现多线程 3.Callable接口创建线程 三.线程的生命周期与状态 四.线程的执行顺序 1.定时器 2.线程的互斥与同步通信 3.线程同步通信技术 一.线程 什么是线程: 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位. 什么是多线程: 多线程指在单个程序中可以同时运行多个不同的线程执行不同的任务. 二.创建多线程的方式 多线程的创建方式有三种:T

  • Java多线程编程详细解释

    目录 一.多线程的优缺点 多线程的优点: 多线程的代价: 二.创建java多线程 1.创建Thread的子类 2.实现Runnable接口 三.线程安全 四.java同步块 五.java线程通信 六.java中的锁 七.java中其他同步方法 八.java中的线程池 参考: 总结 一.多线程的优缺点 多线程的优点: 1)资源利用率更好 2)程序设计在某些情况下更简单 3)程序响应更快 多线程的代价: 1)设计更复杂 虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般都更复杂.在多线程

  • Java多线程之Worker Thread模式

    目录 一.Worker Thread模式 二   .Worker Thread模式中的角色 1.Client(委托者) 2.Channel(通信线路) 3.Worker(工人) 4.Request(请求) 三.Worker Thread使用场景 四.Worker Thread模式程序示例 一.Worker Thread模式 Worker的意思是工作的人,在Worker Thread模式中,工人线程Worker thread会逐个取回工作并进行处理,当所有工作全部完成后,工人线程会等待新的工作到来

  • Java 多线程的同步代码块详解

    目录 synchronized 同步代码块 同步方法(this锁) 静态同步方法 死锁问题 lock 总结 火车站抢票问题 由于现实中买票也不会是零延迟的,为了真实性加入了延迟机制,也就是线程休眠语句 package test.MyThread.ticketDemo; public class RunnableThread implements Runnable{ private int ticket = 100; @Override public void run(){ while(true)

  • Java学习随记之多线程编程

    Process和Thread 程序是指令和数据的有序集合, 本身没有运行的含义,是一个静态的概念. 进程是执行程序的一次执行过程,他是一个动态的概念,是系统资源分配的单位 一个进程中可以包含若干个线程,线程是CPU调度和执行的单位 线程创建 三种创建方法 继承Thread类 //创建线程方法一:继承Thread类,重写run() 方法,调用start开启主线程 public class TestThread01 extends Thread{ @Override public void run(

  • java多线程编程学习(线程间通信)

    一.概要 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就是成为整体的必用方案之一.可以说,使线程进行通信后,系统之间的交互性会更强大,在大大提高cpu利用率的同时还会使程序员对各线程任务在处理过程中进行有效的把控和监督. 二.等待/通知机制 1."wait/notify"机制:等待/通知机制,wait使线程暂停运行,而notify 使暂停的线程继续运行.用一个厨师和服务员的交互来说明: (1) 服务员取到菜的时间取决于厨师,所以服务员就有&

  • Java多线程编程中synchronized关键字的基础用法讲解

    多线程编程中,最关键.最关心的问题应该就是同步问题,这是一个难点,也是核心. 从jdk最早的版本的synchronized.volatile,到jdk 1.5中提供的java.util.concurrent.locks包中的Lock接口(实现有ReadLock,WriteLock,ReentrantLock),多线程的实现也是一步步走向成熟化.   同步,它是通过什么机制来控制的呢?第一反应就是锁,这个在学习操作系统与数据库的时候,应该都已经接触到了.在Java的多线程程序中,当多个程序竞争同一

  • java多线程编程实例

    一.相关知识: Java多线程程序设计到的知识: (一)对同一个数量进行操作 (二)对同一个对象进行操作 (三)回调方法使用 (四)线程同步,死锁问题 (五)线程通信 等等 二.示例一:三个售票窗口同时出售20张票; 程序分析: 1.票数要使用同一个静态值 2.为保证不会出现卖出同一个票数,要java多线程同步锁. 设计思路: 1.创建一个站台类Station,继承Thread,重写run方法,在run方法里面执行售票操作!售票要使用同步锁:即有一个站台卖这张票时,其他站台要等这张票卖完! 2.

  • Java多线程编程实战之模拟大量数据同步

    背景 最近对于 Java 多线程做了一段时间的学习,笔者一直认为,学习东西就是要应用到实际的业务需求中的.否则要么无法深入理解,要么硬生生地套用技术只是达到炫技的效果. 不过笔者仍旧认为自己对于多线程掌握不够熟练,不敢轻易应用到生产代码中.这就按照平时工作中遇到的实际问题,脑补了一个很可能存在的业务场景: 已知某公司管理着 1000 个微信服务号,每个服务号有 1w ~ 50w 粉丝不等.假设该公司每天都需要将所有微信服务号的粉丝数据通过调用微信 API 的方式更新到本地数据库. 需求分析 对此

  • Java多线程编程小实例模拟停车场系统

    下面分享的是一个Java多线程模拟停车场系统的小实例(Java的应用还是很广泛的,哈哈),具体代码如下: Park类 public class Park { boolean []park=new boolean[3]; public boolean equals() { return true; } } Car: public class Car { private String number; private int position=0; public Car(String number)

  • Java多线程编程安全退出线程方法介绍

    线程停止 Thread提供了一个stop()方法,但是stop()方法是一个被废弃的方法.为什么stop()方法被废弃而不被使用呢?原因是stop()方法太过于暴力,会强行把执行一半的线程终止.这样会就不会保证线程的资源正确释放,通常是没有给与线程完成资源释放工作的机会,因此会导致程序工作在不确定的状态下 那我们该使用什么来停止线程呢 Thread.interrupt(),我们可以用他来停止线程,他是安全的,可是使用他的时候并不会真的停止了线程,只是会给线程打上了一个记号,至于这个记号有什么用呢

  • Java多线程编程实现socket通信示例代码

    流传于网络上有关Java多线程通信的编程实例有很多,这一篇还算比较不错,代码可用.下面看看具体内容. TCP是Tranfer Control Protocol的 简称,是一种面向连接的保证可靠传输的协议.通过TCP协议传输,得到的是一个顺序的无差错的数据流.发送方和接收方的成对的两个socket之间必须建 立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以

  • Java多线程编程中synchronized线程同步的教程

    0.关于线程同步 (1)为什么需要同步多线程? 线程的同步是指让多个运行的线程在一起良好地协作,达到让多线程按要求合理地占用释放资源.我们采用Java中的同步代码块和同步方法达到这样的目的.比如这样的解决多线程无固定序执行的问题: public class TwoThreadTest { public static void main(String[] args) { Thread th1= new MyThread1(); Thread th2= new MyThread2(); th1.st

  • java多线程编程技术详解和实例代码

     java多线程编程技术详解和实例代码 1.   Java和他的API都可以使用并发. 可以指定程序包含不同的执行线程,每个线程都具有自己的方法调用堆栈和程序计数器,使得线程在与其他线程并发地执行能够共享程序范围内的资源,比如共享内存,这种能力被称为多线程编程(multithreading),在核心的C和C++语言中并不具备这种能力,尽管他们影响了JAVA的设计. 2.   线程的生命周期 新线程的生命周期从"新生"状态开始.程序启动线程前,线程一直是"新生"状态:

随机推荐