Java小记 多线程

这两篇文章写得真的好:



两种实现方式:

  • 继承Thread
  • 实现Runnable接口

继承Thread

构造Thread实例

  - public Thread()
  - public Thread(String threadName) 创建名为 ThreadName 的线程对象
public class Test extends Thread
{
	private int count=10;
	public void run(){
		while(true){
			System.out.printlnl(count + "");
			if(--count==0){
				return;
			}
		}
	}
	public static void main(String[] args){
		new Test().start();
	}
}
  • 实现线程的代码写在run方法中
  • 调用start方法执行线程(调用run()方法)
  • 主方法调用start方法前,Thread对象仅是一个实例,并不是线程

实现Runnable接口

实现Runnable接口语法:
public class Thread Extends Object implements Runnable

构造方法:
public Thread(Runnable target)
public Thread(Runnable target, String name)
  于是实现了将Runable实例与Thread实例相关联

使用Runnable接口启动新线程的步骤如下:

  • 建立Runnable对象
  • 使用参数为Runnable对象的构造方法创建Thread实例
  • 调用start方法启动线程
Thread t = new Thread(new Runnable(){
				public void run(){
					while(..){
					...
					}
				}
t.start();

线程的生命周期

状态说明
出生start()调用之前都处于出生状态
就绪调用start()后,就绪
运行线程得到系统资源后,运行
等待调用wait()等待。调用notify()唤醒
休眠调用sleep()后,休眠
阻塞运行时发出输入输出请求,阻塞
死亡run()执行完毕后,死亡
  • 使线程进入就绪状态
  • sleep()
  • wait()
  • 等待输入、输出完成

  • 使线程由就绪到运行
  • notify()
  • notifyAll() 唤醒所有等待状态线程
  • interrupt()
  • 休眠时间结束
  • 输入、输出结束

线程的加入 join()

  • 某线程使用join()方法加入另一线程时,另一线程会等待该线程执行完毕再执行。
Thread threadA = new Thread(new Runnable(){
						int count=0;
						public void run(){
							while(true){
							...
							threadB.join();
							}
						}
					}

线程让步

  • Thread.yield()方法。暂停当前正在执行的线程对象,把执行机会让给相同或者更高优先级的线程。

线程的优先级 setPriority()

  • 新线程继承父类优先级
  • 优先级1-10
常数优先级
Thread.MAX_PRIORITY10
Thread.MIN_PRIORITY1
Thread.NORM_PRIORITY5
Thread thread_a = new Thread();
setPriority("thread_a", 5, thread_a);
thread_a.setPriority(5);
thread_a.setName(name);	//设置线程名字

线程同步

  • 线程同步机制——解决资源访问冲突

线程同步机制


同步块 synchronized

  • 把共享资源放在同步块(临界区)
synchronized(Object){
}

同步方法 synchronized

  • 必须将每个能访问共享资源的方法修饰为synchronized
synchronized void func(){
}
public synchronized void doit(){
	if(num>0){
		try{
			Thread.sleep(10);
		}catch(Exception e){
			e.printStackTrace();
		}
		System.out.println("tickets" + --num);
	}
}
public void run(){
	while(true){
		doit();
	}
}

synchronized 具体应用

  • 实例方法
  • 静态方法
  • 同步代码块

1. 作用于实例方法

public class Test implements Runnable{
    //共享资源/临界资源
    static int i=0;


    // synchronized 修饰实例方法
    public synchronized void increase(){
        i++;
    }
    @Override
    public void run() {
        for(int j=0;j<1000;j++){
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Test instance=new Test();
        Thread t1=new Thread(instance);
        Thread t2=new Thread(instance);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}

输出:
>>> 2000

  • 如果实例不同,那就是不同的实例方法,谁也锁不着谁了。
public static void main(String[] args) throws InterruptedException {
    Thread t1=new Thread(new Test());
    Thread t2=new Thread(new Test());
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println(i);
}

2. 作用于静态方法

public class Test implements Runnable{
    static int i=0;

	// 作用于静态方法,锁是当前class对象
    public static synchronized void increase(){
        i++;
    }

	// 非静态,访问时锁不一样(实例对象不一样) 不会 发生互斥
    public synchronized void increase4Obj(){
        i++;
    }

    @Override
    public void run() {
        for(int j=0;j<1000000;j++){
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        //new新实例
        Thread t1=new Thread(new Test());
        //new另一个实例
        Thread t2=new Thread(new Test());
        //启动线程
        t1.start();t2.start();
        t1.join();t2.join();
        System.out.println(i);
    }
}
  • 作用于静态方法,就不用但是实例对象不一样的问题了。

3. 同步代码块

public class Test implements Runnable{
    static Test instance=new Test();
    static int i=0;
    @Override
    public void run() {
        //...do something...
        //锁对象为instance
        synchronized(instance){
            for(int j=0;j<1000000;j++){
                    i++;
              }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(instance);
        Thread t2=new Thread(instance);
        t1.start();t2.start();
        t1.join();t2.join();
        System.out.println(i);
    }
}

  • 实例对象锁【同上】
public static void run(){
	synchronized(this){
		for(...){
		...
		}
	}
}
  • class对象锁
public static void run(){
	synchronized(Test.class){
		for(...){
		...
		}
	}
}
import static java.lang.System.out;
import java.util.*;
import Tools.Tools;

// 同步代码块
public class TrySome implements Runnable{
	// 用于 run() for循环中累加
    static int value = 0;
   	// 计算 list 中数值求和
    static int sum=0;
    // 记录 list 中最大、最小值
    static double max=0, min=Double.POSITIVE_INFINITY;
    // 创建一 int ArrayList
    static List<Integer> list = new ArrayList<>();
    // 这是自己编写的一个简单工具类
    static Tools tool = new Tools();

    private String name="None";
    private String say="None";
	
	// 构造方法
    public TrySome(String name, String words)
    {
        this.name = name;
        this.say = words;

    }
    public TrySome(){}

	// run() 方法
    public void run()
    {
        out.println("I am " + name + ".   I say: " + say);
        synchronized(TrySome.class){
            for(int i=0;i<2e5;i++)
            {
                value++;
            }
            mk_list();
            Iterator<Integer> itr = list.iterator();
            while(itr.hasNext())
            {
                int data = itr.next();
                sum += data;
                if(data>max)
                {
                    max = data;
                }
                if(data<min)
                {
                    min = data;
                }
            }
        }
    }

    public static void mk_list()
    {
        for(int i=0;i<40;i++)
        {
            list.add(tool.randint(20, 200));
        }
    }

    public static void main(String[] args) throws Exception
    {
        Thread t1 = new Thread(new TrySome("Fry", "Hello future!"));
        Thread t2 = new Thread(new TrySome("Bender", "Bite my shiny metal ass!"));
        t1.start();t2.start();t2.join();
        out.println(value);
        // ==========================================
        out.println("average: "+ (sum/80) + "  max:" + max + "  min: " + min);
    }
}
import static java.lang.System.out;
import java.util.*;
import Tools.Tools;

public class FurtherM implements Runnable{
    List<Double> list = new ArrayList<>();
    static double sum=0;
    static List<Double> summ = new ArrayList<>();
    static Tools t = new Tools();
    String name;
    public FurtherM(List<Double> lst, String name)
    {
        list = lst;
        this.name = name;
    }
    public void run()
    {
        Iterator<Double> itr = list.iterator();
        synchronized(FurtherM.class)
        {
            while(itr.hasNext())
            {
                sum += itr.next();
            }
        }
        out.println(name + "   is over!");

    }

    public static List<Double> mk_list()
    {
        List<Double> lst = new ArrayList<>();
        double sumall=0;
        for(int i=0;i<40;i++)
        {
            double data = t.randf_format(1, 1, 40);
            sumall += data;
            lst.add(data);
        }
        summ.add(sumall);
        out.println(sumall);
        return lst;
    }

    public static void main(String[] args) throws InterruptedException
    {
        Thread t1 = new Thread(new FurtherM(mk_list(), "One"));
        Thread t2 = new Thread(new FurtherM(mk_list(), "Two"));
        t1.start();t2.start();
        t1.join();t2.join();
        out.println("sum: " + sum);
        out.println("allsum:  " + (summ.get(0) + summ.get(1)));
    }
}

Tools

import java.text.DecimalFormat;
import java.util.Date;
import java.util.Random;

/*****************************************************************
 * ****** 属性 *******
 * - d : Date()
 * - r : Random()
 * - myFormat : DecimalFormat()
 *
 * --------方法-------------
 * print(Number...) | print(String)
 * format_(pattern, data)
 * randint(from, to) | randf(from, to)
 * randf_format(n, from, to)  -- 小数位数 n 位
 *
 *
 ******************************************************************/
public class Tools {
    Date d = new Date();
    int seed = Integer.parseInt(String.format("%ts", d));
    Random r = new Random(seed);
    DecimalFormat myFormat = new DecimalFormat();


    public void print(String s) {
        System.out.println(s);
    }

    public void print(Number... a) {
        StringBuilder s = new StringBuilder();
        for (Number j : a) {
            s.append(j).append("\t");
        }
        System.out.println(s);
    }

    public String format_(String pattern, double data) {
        myFormat.applyPattern(pattern);
        return myFormat.format(data);
    }

    public int randint(int from, int to) {
        return from + (int) (r.nextInt(to - from));
    }

    public double randf(double from, double to) {
        return from + (to - from) * r.nextDouble();
    }

    /***********************************************
     // return double
     // n:小数位数 from ~ to
     ************************************************/
    public double randf_format(int n, double from, double to) {
        StringBuilder pattern = new StringBuilder("0.");
        pattern.append("0".repeat(n));
        String s = this.format_(pattern.toString(), randf(from, to));
        return Double.parseDouble(s);
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Protobuf是一种高效的序列化协议,可以用于数据交换和数据存储。它的主要优势是大小小,速度快,可扩展性强。下面是使用Protobuf的一些小记: 1. 定义消息格式 首先,需要定义消息格式,以便Protobuf可以将数据序列化和反序列化。消息格式定义在.proto文件中,使用protobuf语言编写。例如,下面是一个简单的消息格式定义: ``` syntax = "proto3"; message Person { string name = 1; int32 age = 2; } ``` 这个消息格式定义了一个名为Person的消息,包含两个字段:name和age。 2. 生成代码 一旦消息格式定义好,就可以使用Protobuf编译器生成代码。编译器将根据消息格式定义生成相应的代码,包括消息类、序列化和反序列化方法等。可以使用以下命令生成代码: ``` protoc --java_out=. message.proto ``` 这将生成一个名为message.pb.javaJava类,该类包含Person消息的定义以及相关方法。 3. 序列化和反序列化 一旦生成了代码,就可以使用Protobuf序列化和反序列化数据。例如,下面是一个示例代码,将一个Person对象序列化为字节数组,并将其反序列化为另一个Person对象: ``` Person person = Person.newBuilder() .setName("Alice") .setAge(25) .build(); byte[] bytes = person.toByteArray(); Person deserializedPerson = Person.parseFrom(bytes); ``` 这个示例代码创建了一个Person对象,将其序列化为字节数组,然后将其反序列化为另一个Person对象。在这个过程中,Protobuf使用生成的代码执行序列化和反序列化操作。 以上是使用Protobuf的一些基本步骤和注意事项,希望对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定谔的壳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值