Java基础(四)线程快速了解

开始整理线程之前,之前有个命令忘记整理了,先整理一下jar命令的使用

Jar包

其实可以理解是java的压缩包 方便使用,只要在classpath设置jar路径即可 数据库驱动,ssh框架等都是以jar包体现的

打包方式一:将指定的class文件打入到jar包中 jar cvf xxx.jar Xxx.class yyy.class

打包方式二:将某个目录下的所有文件打入到jar包中 jar cvf xxx.jar -C xxx/.

查看jar文件: jar -tf xxx.jar

运行jar包中的类: java -cp xxx.jar xx.xx.xx(完整的类名)

常用的jar命令参数: c:创建压缩文件 f:指定存档名称 v:显示详细信息 m:加入自定义清单

指定清单文件(xxx.jar/META-INF/MNIFEST.MF)的入口类 jar cvfe classess.jar com.zhaofan.PackagDemo1 classes/. 这样我们就可以通过java -jar xxx.jar直接执行

线程

进程:运行时概念,运行的应用程序 线程:应用程序内部并发执行的代码段,共享内存

这里几个关键词 yield: 放弃cpu抢占权 join:等待指定的线程执行完 sleep:静态方法,让线程休眠毫秒数 daemo:守护线程

最简单的线程代码:

package study_java.ex9;

public class ThreadDemo1 {
    public static void main(String[] args){
        Mythread t1 = new Mythread();
        t1.start();
    }
}

class Mythread extends Thread{
    public void run(){
        while (true){
            System.out.println("MyThread");
        }

    }
}

join的一个简单实用例子:

package study_java.ex9;

public class ThreadDemo2 {
    public static void main(String[] args){
        Player p1 = new Player("aa",5000);
        Player p2 = new Player("bb",8000);
        Player p3 = new Player("cc",2000);
        Player p4 = new Player("dd",3000);
        p1.start();
        p2.start();
        p3.start();
        p4.start();
        try{
            p1.join();
            p2.join();
            p3.join();
            p3.join();
        }
        catch (Exception e){

        }


        System.out.println("人到了,开始玩游戏");
    }
}

class Player extends Thread{
    private String name;
    private int time;
    public Player(String name, int time){
        this.name = name;
        this.time = time;
    }
    public void run(){
        System.out.println("玩家:"+name + "出发了");
        try{
            Thread.sleep(time);
        }
        catch (Exception e){

        }
        System.out.println("玩家:"+name + "到了");


    }
}

守护线程的一个使用例子

package study_java.ex9;

import java.util.Date;

public class ThraedDemo3 {
    public static void main(String[] args){
        Room r1 = new Room("no1",15000);
        Waiter w1 = new Waiter();
        //w1.setDaemon(true); 设置守护线程
        r1.start();
        w1.start();
    }
}

class Room extends Thread{
    private String no;
    private int time;

    public Room(String no, int time){
        this.no = no;
        this.time = time;
    }

    public void run(){
        System.out.println("no" + "号房间正在唱歌");
        try{
            Thread.sleep(time);
        }
        catch (Exception e){

        }
        System.out.println("no" + "买单");
    }
}

class Waiter extends Thread{
    public Waiter(){
        this.setDaemon(true);
    }
    public void run(){
        while (true){
            System.out.println(new java.util.Date());
            try{
                Thread.sleep(1000);
            }
            catch (Exception e){

            }
        }
    }
}

任何一个对象都可以是锁,信号灯,其实就是一个参照物 一个锁的代码例子:

package study_java.ex9;

public class ThreadDemo4 {
    public static void main(String[] args){
        Saler s1 = new Saler("a1");
        Saler s2 = new Saler("a2");
        s1.start();
        s2.start();
    }
}

class Saler extends Thread{
    // 锁
    static Object lock = new Object();

    static int tickts = 100;
    private String name;
    public Saler(String name){
        this.name = name;
    }
    public void run(){
        while (true){
            int tick = getTickts();
            if (tick > 0){
                System.out.println(name+":"+ tick);
            }
            else {
                return;
            }
        }
    }
    // 取票
    public int getTickts(){
        synchronized (lock){
            int currTicket = tickts;
            tickts --;
            return currTicket;
        }
    }
}

还有一种方法是:

public static synchronized int getTickts(){
   int currTicket = tickts;
   tickts --;
   return currTicket;
}

这样也能实现锁的机制,但是注意这里必须是static

我们整理一个新的写法,把票池单独写出来

public class ThreadDemo2 {
    public static void main(String[] args){
        TicketPool pool = new TicketPool();
        Saler s1 = new Saler("s1",pool);
        Saler s2 = new Saler("s2",pool);
        s1.start();
        s2.start();
    }
}

// 票池
class TicketPool {
    private int tickets = 100;
    // 从票池取票
    public synchronized int getTickets(){
        int ticket = tickets;
        tickets -= 1;
        return ticket;
    }
}
// 售票员
class Saler extends Thread{
    private TicketPool pool = null;
    private String name;
    public Saler(String name, TicketPool tp){
        this.name = name;
        this.pool = tp;
    }
    public void run(){
        while (true){
            int no = pool.getTickets();
            if (no > 0 ){
                System.out.println(name + ":" + no);
            }
            else {
                return;
            }
        }
    }
}

两个小的练习熟悉上面知识点的使用: 车过山洞的问题,山洞同时只允许一个车通过,现在有多辆车,不同的车通过的时间不同,代码实现如下:

package study_java.ex11;

public class CarCave {
    public static void main(String[] args){
        Cave cave = new Cave();
        Car car1 = new Car(cave,10000,"奥迪");
        Car car2 = new Car(cave,8000,"奔驰");
        Car car3 = new Car(cave,6000,"宝马");
        Car car4 = new Car(cave,2000,"悍马");
        car1.start();
        car2.start();
        car3.start();
        car4.start();

    }
}

class Cave{

    public synchronized void crossCar(Car car){
        try{
            System.out.println(car.name+":开始过山洞了");
            Thread.sleep(car.time);
            System.out.println(car.name+":开始出山洞了");
        }
        catch (Exception e){

        }


    }
}

class Car extends Thread{
    public Cave cave;
    public int time;
    public String name;

    public Car(Cave cave ,int time,String name){
        this.cave = cave;
        this.time = time;
        this.name = name;
    }
    public void run(){
        cave.crossCar(this);
    }
}

第二个小练习是我们经常遇到的场景,取票问题,现在有一个取票机,但是有五十个人要取票,实现代码如下:

package study_java.ex11;

public class TicketDemo1 {
    public static void main(String[] args){
        TicketMachine m = new TicketMachine();
        for (int i=0;i<50;i++){
            new Person(m,"tom"+i).start();
        }
    }
}


// 取票机
class TicketMachine{
    private int ticketNo = 1;
    // 打印票号
    public synchronized int printTicktNo(){
        int currTicketNo = ticketNo;
        ticketNo ++;
        return currTicketNo;
    }
}

class Person extends Thread{
    private TicketMachine m;
    private String name;
    public Person(TicketMachine m,String name) {
        this.m = m;
        this.name = name;
    }
    public void run(){
        int no = m.printTicktNo();
        System.out.println(name+ ":" + no);
    }
}

生产者消费者模型

通过上面的知识点,写一个生产者好消费者模型

package study_java.ex11;

import java.util.LinkedList;
import java.util.List;

public class PCDemo1 {
    public static void main(String[] args){
        MyList myList = new MyList();

        Productor p = new Productor(myList);
        Consumer c = new Consumer(myList);
        Consumer c2 = new Consumer(myList);
        Consumer c3 = new Consumer(myList);
        p.start();
        c.start();
        c2.start();
        c3.start();
    }

}

class MyList{
    private int Max = 100;
    private List<Integer> list = new LinkedList<Integer>();
    public  void addLast(Integer i){
        while (true){
            synchronized (list){
                if (list.size() < Max){
                    list.add(i);
                    return;
                }
            }
        }


    }
    public  Integer removeFirst(){
        while (true){
            synchronized (list){
                if(!list.isEmpty()){
                    return list.remove(0);
                }
            }
        }
    }
}

class Productor extends Thread{
    private MyList myList;
    public Productor(MyList myList){
        this.myList = myList;
    }
    public void run(){
        int i = 1;
        while (true){
            myList.addLast(new Integer(i));
            System.out.println("生产者生产了"+i+"号");
            i++;
        }
    }
}

class Consumer extends Thread{
    private MyList myList;
    public Consumer(MyList myList){
        this.myList = myList;
    }
    public void run(){
        while (true){
            int no = myList.removeFirst();
            System.out.println("消费者消费了"+no+"号");
        }
    }
}

生产者消费者而改进版本:

package study_java.ex11;

import java.util.LinkedList;
import java.util.List;

public class PCDemo5 {
    public static void main(String[] args){
        Pool pool = new Pool();
        Producter p1 = new Producter(pool);
        Consumer c1 = new Consumer(pool);
        p1.start();
        c1.start();

    }
}

class Pool{
    private List<Integer> list = new LinkedList<Integer>();
    private int Max = 100;
    public void addLast(int n){
        synchronized (this){
            while (list.size() >= Max){
                try{
                    this.wait();
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
            list.add(new Integer(n));

            this.notifyAll();
        }
    }
    public int remove(){
        synchronized (this){
            while (list.size() == 0){
                try{
                    this.wait();
                }
                catch (Exception e){
                    e.printStackTrace();
                }

            }
            int no = list.remove(0);

            this.notifyAll();
            return no;
        }
    }

}

// 生产者
class Producter extends Thread{
    private Pool pool;
    static int i = 1;
    public Producter(Pool pool){
        this.pool = pool;
    }
    public void run(){
        while (true){
            pool.addLast(i++);
            System.out.println("生产者生产了"+i+"号");
        }
    }

}


// 消费者
class Consumer extends Thread{
    private Pool pool;
    public Consumer(Pool pool){
        this.pool = pool;
    }
    public void run(){
        while (true){
            int no = pool.remove();
            System.out.println("消费者消费了"+no+"号");
        }
    }

}

wait():让当前线程进入到锁对象的等待队列里,同时释放锁旗标。这个方法是当前锁对象的方法 wait这里还可以添加参数wait(int n) :等待指定的时间片,等待队列中的线程最多等待n毫秒

notify():这个方法是当前锁对象的方法,注意这里并不会释放锁 notifyAll():通知等待队列中的所有线程都可以抢占cpu运行,通知需要获得对象的监控权

sleep:当前CPU的抢占权,和锁对象的监控权无关。 Thread.currentThread().getName():获取当前线程名字 Thread.currentThread().setName():设置当前线程名字

priority:1-10从低到高,默认是5 Thread.currentThread().getPriority():设置当前线程优先级

线程状态: BLOCKED: 阻塞 NEW:新建 RUNNABL:执行 TERMINATED:已经终止 TIMED_WAITING:限时等待 WAITING:等待

创建一个线程的另外一种方式: 实现Runnable接口 1. 子类覆盖接口中的run方法 2. 通过Thread类创建线程,并将实现了Runnable接口的子类对象作为参数传递给Thread类的构造函数 3. Thread类对象调用start方法开启线程

代码例子如下:

package study_java.ex11;

public class RunnableDemo1 {
    public static void main(String[] args){
        MyRunnabl m = new MyRunnabl();
        new Thread(m).start();
    }
}

class MyRunnabl implements Runnable{
    public void run(){
        System.out.println("hello world");
    }
}

同步(synchronized)

synchronized(对象) { 需要同步的代码 } 同步的特点: 同步的前提是: 需要两个或者两个以上的线程 多个线程使用的同一个锁

同步的弊端: 当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的额运行效率

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据之美

MapReduce 中的两表 join 几种方案简介

1. 概述 在传统数据库(如:MYSQL)中,JOIN操作是非常常见且非常耗时的。而在HADOOP中进行JOIN操作,同样常见且耗时,由于Hadoop的独...

2035
来自专栏Java帮帮-微信公众号-技术文章全总结

Java中的24种设计模式与7大原则

一、创建型模式 1、抽象工厂模式(Abstract factory pattern): 提供一个接口, 用于创建相关或依赖对象的家族, 而不需要指定具体类. 2...

3607
来自专栏码洞

基于Netty实现Redis协议的编码解码器

上面是Netty的服务器端基本消息处理结构,为了便于初学者理解,它和真实的结构有稍许出入。Netty是基于NIO的消息处理框架,用来高效处理网络IO。处理网络消...

2521
来自专栏小勇DW3

自己手动写代码实现数据库连接池

池:一个高级的集合体(集合存储元素 + 管理方式–>提高效率),是对外提供同一种类型对象的集合,如(线程池、数据库连接池)  特性:复用性(每条连接可重复使用)...

1503
来自专栏Nian糕的私人厨房

ECMAScript7 async/await 异步解决方案

Async 函数作为异步解决方案的最优解,async/await 特性能让我们编写出相比回调地狱和 Promise 链式调用更直观、更容易理解的代码,Async...

785
来自专栏猿份到

LeakCanary源码浅析

在Android开发中最让人们头疼的就是内存泄漏了,今天来介绍一个查看内存是否泄漏的工具LeakCanary,并通过研究源码明白它是如何分析和查找存在泄漏信息的...

3495
来自专栏瓜大三哥

文件地址映射之yaffs_GetTnode

yaffs文件系统在更新文件数据的时候,会分配一块新的chunk,也就是说,同样的文件偏移地址,在该地址上的数据更新前和更新后,其对应的flash上的存储地址是...

1976
来自专栏陈树义

简单笔记

1、类的表面类型和实际类型 实例对象有两个类型:表面类型(Apparent Type)和实际类型(ActualType),表面类型是声明时的类型,实际类型是对象...

2595
来自专栏编程

如何修改动态代理的私有变量

最近在写一个 Spring Controller 的 JUnit 单元测试时,需要将一个Mock对象塞入到Controller的私有成员变量中,发现怎么都塞不成...

1989
来自专栏吴伟祥

手写tomcat监控工具---宕机重启 原

2733

扫码关注云+社区

领取腾讯云代金券