Java学习笔记之多线程操作

 以前学习基础的时候学习了一段时间的多线程,上课的时候老师也讲过一遍,那时候感觉学的似懂非懂。因为到现在很长一段时间没有用到多线程的知识,所以现在基本上忘了差不多了。但是下个星期要面试了,所以今天特意又研究了一下多线程,免得被问到多线程问题时什么都不记得了那就麻烦了。现在对java比较熟悉了,所以再一次学习多线程知识,感觉没有那么难了(记得刚接触多线程的时候,感觉非常吃力)。

  首先讲一下进程和线程的区别:

    进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。

    线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。

    线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。

    多进程是指操作系统能同时运行多个任务(程序)。

    多线程是指在同一程序中有多个顺序流在执行。

  在java中创建一个线程有两种方法:

    ①实现java.lang.Runnable接口,重写run()方法,启动:new Thread(this).start()。
    

package com.thread;

public class ThreadTest1 {
    public static void main(String[] args) {
        Runnable1 r = new Runnable1();
        //r.run();并不是线程开启,而是简单的方法调用
        Thread t = new Thread(r);//创建线程
        //t.run(); //如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
        t.start(); //线程开启
        for (int i = 0; i < 100; i++) {
            System.out.println("main:"+i);
        }
    }
}
class Runnable1 implements Runnable{
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("Thread-----:"+i);
        }
    }
}

 1.r.run()并不是启动线程,而是简单的方法调用。

    2.Thread也有run()方法,如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。

    3.并不是一启动线程(调用start()方法)就执行这个线程,而是进入就绪状态,什么时候运行要看CUP。

    ②继承java.lang.Thread类,重写run()方法。
    

package com.thread;

public class TestThread2 {
    public static void main(String[] args) {
        Thread1 t = new Thread1();
        //t.run(); //这里也不能直接调用方法
        t.start();
        for (int i = 0; i < 100; i++) {
            System.out.println("main:"+i);
        }
    }
}

//尽量使用实现Runnnable接口,因为接口比较灵活
class Thread1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("Thread-----:"+i);
        }
    }
}
package com.thread;
import java.util.Date;
/**
 * sleep()指在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
 * @author Administrator
 *
 */
public class SleepTest {
    public static void main(String[] args) {
        Thread2 t = new Thread2();
        t.start();
        try {
            Thread.sleep(10000); //主线程睡眠10秒钟
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //主线程睡眠10秒钟后结束t线程
        //t.interrupt(); //这种结束方式比较粗暴,如果t线程打开了某个资源还没来得及关闭也就是run方法还没有执行完就强制结束线程,会导致资源无法关闭
        //t.stop();也是结束某个线程,这种方式比interrupt()更粗暴
        t.flag = false;
    }
}
class Thread2 extends Thread{
    boolean flag = true; //用这种方式结束线程很不错,用一个变量控制run方法什么时候不再执行,不会出现run方法没有执行完毕就结束
    @Override
    public void run() { //run方法一结束,整个线程就终止了
        while(flag){
            System.out.println("---"+new Date()+"---");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                return;
            }
        }
    }
}

②join():指等待t线程终止。也可以理解为将t线程合并到当前线程来,等待t线程结束后再往下执行。相当于方法调用

package com.thread;

import java.util.Date;

/*
 * t.join()方法指等待t线程终止。也可以理解为将t线程合并到当前线程来,等待t线程结束后再往下执行。相当于方法调用
 */
public class TestJoin {
    public static void main(String[] args) {
        Thread t = new Thread3("abc");
        t.start();
        for (int i = 0; i < 20; i++) {
            System.out.println("我是main线程");
            if(i==10){
                try {
                    t.join();
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Thread3 extends Thread{
    public Thread3(String s) { //给该线程取一个名字,用getName()方法可以去到该名字
        super(s);
    }
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("我是"+getName()+"线程");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

总结

1.线程是一个动态的对象,是处理机调度的一个基本单位,表示一个进程的控制点。
2.进程是系统资源的分配单位,是程序的一次执行过程,一个进程同时可以拥有多个线程。
3.同步 :是程序解决不同线程访问统一资源是的顺序执行机制。
4.实现同步的机制主要有临界区、互斥、信号量和事件
临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资 源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。
互斥量:采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享 .互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目 。信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。
事件:通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作 。
5趣说同异步:同步和异步的概念对于很多人来说是一个模糊的概念,是一种似乎只能意会不能言传的东西。其实我们的生活中存在着很多同步异步的例子。比如:你叫我去吃饭,我听到了就立刻和你去吃饭,如果我们有听到,你就会一直叫我,直到我听见和你一起去吃饭,这个过程叫同步;异步过程指你叫我去吃饭,然后你就去吃饭了,而不管我是否和你一起去吃饭。而我得到消息后可能立即就走,也可能过段时间再走。如果我请你吃饭,就是同步,如果你请我吃饭就用异步,这样你比较省钱。哈哈哈。。。
6.计算机领域,同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
7.而我们平时经常讨论的同步问题多发生在多线程环境中的数据共享问题。即当多个线程需要访问同一个资源时,它们需要以某种顺序来确保该资源在某一特定时刻只能被一个线程所访问,如果使用异步,程序的运行结果将不可预料。因此,在这种情况下,就必须对数据进行同步,即限制只能有一个进程访问资源,其他线程必须等待。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小新杂谈社

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

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

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

打赏作者

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

抵扣说明:

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

余额充值