Java线程与进程

进程与线程的关系

  进程里面至少有一个线程,进程间的切换会有较大的开销

  线程必须依附在进程上,同一进程共享代码和数据空间

多线程的优势

  多线程可以达到高效并充分利用cpu

线程使用的方法

继承Thread类使用线程

public class Test{
    public static void main(String[] args){
        MyThread t = new MyThread("x1x");
        t.start();      // 启动线程
    }
}

// 自定义一个类,继承Thread类,重写run()方法
class MyThread extends Thread{
    private Thread thread;
    private String threadName;

    public MyThread(String threadName){
        this.threadName = threadName;
    }

    @override
    public void run(){
        System.out.println("线程名称:" + threadName);
        for(int i = 0; i < 5; i++){
            System.out.println("Thread:" + threadName + "-----" + i);
        }
    }

    public void start(){
        if(null == thread){
            thread = new Thread(this, threadName);
            thread.start();
        }
    }
}    

继承Thread类

实现Runnable接口使用线程 

 public class Test{
     public static void main(String[] args){
         MyRunnable m = new MyRunnable("r1r");
         m.start();
     }
 }

 // 实现Runnable接口,实现run()方法
 class MyRunnable implements Runnable{
     private Thread thread;
     private String threadName;
     // 构造方法
     public MyRunnable(String threadName){
         this.threadName = threadName;
     }

     @override
     public void run(){
         System.out.println("线程名称: " + threadName);
         for(int i = 0; i < 6; i++){
             System.out.println("Thread: " + threadName + "----" + i);
         }
     }

     public void start(){
         if(null == thread){
             thread = new Thread(this, threadName);
             thread.start();
         }
     }
 }

实现Runnable接口

实现Callable接口使用线程

 public class MyCallable implements Callable<Integer>{
     public static void main(String[] args){
         MyCallable mc = new MyCallable();
         // 这里的泛型里面填写的类型也与实现Callable时填写的一致
         FutureTask<Integer> fTask = new FutureTask<>(mc);
         new Thread(fTask, "带返回值的线程").start();
         System.out.println(fTask.get());    // 拿到返回值
     }

     /*
      * call()的返回值类型和实现Callable时填写的类型一致,比如这里是Integer类型,那么
      * call()方法的返回值类型就是Integer类型
     */
     @override
     public Integer  call() throws Exception{
         for(int i = 0; i < 100; i++){
             System.out.println(Thread.currentThread().getName() + "----" + i);
         }
         return i;
     }
 }

实现Callable接口

用匿名内部类的形式使用线程

 public class Test{
     public static void main(String[] args){
         // 利用Thread类实现
         new Thread(){
             @override
             public void run(){
                 while(true){
                     System.out.println(Thread.currentThread().getName());
                 }
             }
         }.start();

         // 利用Runnable接口实现
         new Thread(new Runnable(){
             @override
             public void run(){
                 while(true){
                     System.out.println(Thread.currentThread().getName());
                 }
             }
         }).start();
     }
 }

内部类形式调用

继承Runnable和Callable接口比继承Thread类的优势

  • 适合多个相同的程序代码的线程去处理同一个资源
  • 可以避免java中的单继承的限制
  • 增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

线程的优先级

java中的线程是具有优先级的,优先级高的线程会获得更多的运行机会。

java中线程的优先级是用整数来表示的,取值范围是1 - 10

Thread类中有三个静态常量表示优先级:

  static int MAX_PRIORITY   线程可以具有的最高优先级,取值为10

  static int MIN_PRIORITY    线程可以具有的最低优先级,取值为1

  static int NORM_PRIORITY  分配给线程的默认优先级,取值为5

如果要对线程设置优先级或者获取线程的优先级,可以使用Thread类的setPriority 和 getPriority方法分别得到和获取

线程的常用方法

  sleep()     强迫线程睡眠

  join()        等待线程终止

  currentThread()    得到当前方法所在的线程

  isDaemon()    一个线程是否为守护线程

  setDaemon()    设置一个线程为守护线程

  setName()      为线程设置名称

  wait()      强迫线程等待

  interrupt()    终止线程

  notify()  notifyAll()   通知线程继续执行

  setPriority()     设置优先级

  getPriority()     获取优先级

同步

使用synchronized同步锁

  1. 获得同步锁
  2. 清空工作内存
  3. 从主内存拷贝对象到工作内存
  4. 刷新主内存
  5. 释放同步锁
 /*
  * 这个程序的本意是第一个线程先输出zhangsan,然后第二个线程输出lisi
  * 但是由于两个线程同步执行,第一个线程调用output()方法还未结束,第二个线程就已
  *经开始调用output()方法
  * 最终的输出就会是zlhiasnigsan
  * 就好比两个工人在同一时间使用同一机器加工零件,那不就乱套了吗?
  */

 public class synchronizedTest {
     public static void main(String[] args) {
         final Outputter o = new Outputter();
         new Thread() {
             public void run() {
                 o.output("zhangsan");
             }
         }.start();
         new Thread(new Runnable() {

             @Override
             public void run() {
                 // TODO Auto-generated method stub
                 o.output("lisi");
             }
         }).start();
     }
 }

 class Outputter{
     // 放在代码块前面
     public void output(String name) {
         for(int i = 0; i < name.length(); i++) {
             System.out.print(name.charAt(i));
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }
     }
 }

没有同步带来的问题

 /*
  * 在要调用的output()方法前面加上synchronized同步锁就可以解决上述问题
  * 当使用同步锁后,同一对象在同一时间只允许一个线程使用
  * 也就是说,第一个线程调用output()方法,在进入方法后,synchronized就
  * 上锁了,后面的线程就不能调用了,必须等待当前线程执行完output()方法释放锁后
  * 后面的线程才允许调用
  * 就好比第一个工人要开始使用机器加工零件了,在使用机器前,他将房门锁住了,于是
  * 后面
  * 的工人便不能进房间使用机器,必须等工人一加工完零件,将锁打开,第二个工人才能
  * 进去
  * 加工零件
  */

 public class synchronizedTest {
     public static void main(String[] args) {
         final Outputter o = new Outputter();
         new Thread() {
             public void run() {
                 o.output("zhangsan");
             }
         }.start();
         new Thread(new Runnable() {

             @Override
             public void run() {
                 // TODO Auto-generated method stub
                 o.output("lisi");
             }
         }).start();
     }
 }

 class Outputter{
     // 放在代码块前面
     public synchronized void output(String name) {
         for(int i = 0; i < name.length(); i++) {
             System.out.print(name.charAt(i));
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }
     }
 }

使用同步解决问题1

 /*
  * 第二种使用synchronized的方法就是将synchronized
  * 放在要上锁的代码块前面,原理与上述一致
  */

 public class synchronizedTest {
     public static void main(String[] args) {
         final Outputter o = new Outputter();
         new Thread() {
             public void run() {
                 o.output("zhangsan");
             }
         }.start();
         new Thread(new Runnable() {

             @Override
             public void run() {
                 // TODO Auto-generated method stub
                 o.output("lisi");
             }
         }).start();
     }
 }

 class Outputter{
     public void output(String name) {
         // 放在代码块前面
         synchronized(this) {
             for(int i = 0; i < name.length(); i++) {
                 System.out.print(name.charAt(i));
                 try {
                     Thread.sleep(1000);
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
             }
         }
     }
 }

使用同步锁解决问题2

synchronized(){

}的括号里面放的是需要互斥的对象,就是两个工人加工零件使用的同一个机器

使用volatile同步变量

volatile使变量对线程具有可见性

java线程与进程的更多相关文章

  1. JAVA线程和进程区别

    1,JAVA线程和进程区别? (1)简单来讲一个运行的程序就是一个进程,一个进程中可以有多个线程(线程是程序执行的最小单元). (2)线程有四种状态:运行,就绪,挂起,结束 (3)使用多线程的好处 使 ...

  2. Java线程和进程相关面试题与答案总结

    有几天没有写一写博客了,今天就带给大家一些面试题和参考答案吧! 这些都是上海尚学堂Java培训的学员去面试时遇到的问题,今天总结出来的是Java线程相关类的面试题.把参考答案和解析也发布出来,供大家学 ...

  3. 关于java线程、进程的一些问题

    1.多核硬件上,java中同一个进程的多个线程可以运行在不同的CPU上么? 应该是可以的,在eclipse上面跑一个模拟程序,一个死循环的线程可以占用系统(4核,Win7)%的CPU,4个这样的线程刚 ...

  4. Java线程和进程

    一.线程 1.什么是线程: 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.一个进程至少包含一个线程,也可以多个,线程属于进程. 2.Java中线程经历的四个 ...

  5. java线程,进程,多线程

    (1)线程和进程 通俗一点,进程就是一个应用程序在处理机上的一次执行过程,它是一个动态的概念,而线程是进程中的一部分,进程包含多个线程在运行. (2)java中实现线程的两种方式,第一种是继承Thre ...

  6. 菜鸡的Java笔记 第三十七 - java 线程与进程

    线程与进程        线程与进程的区别                最早的的时候DOS 系统有一个特点:只要电脑有病毒,那么电脑就死机了,是因为传统的DOS 系统属于单进程的操作系统       ...

  7. java线程与进程的比较

    线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元:而把传统的进程称为重型进程(Heavy—Weight Process),它相当于只有一个线程的任 ...

  8. java线程基础梳理

    java线程 概述 进程:运行时概念,运行的应用程序,进程间不能共享内存 线程:应用程序内并发执行的代码段,可以共享堆内存和方法区内存,而栈内存是独立的. 并发理解:在单核机器上,从微观角度来看,一段 ...

  9. Java中的进程和线程

     Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是 ...

随机推荐

  1. "双非"应届生校招如何获得大厂青睐?(内附技术岗超全求职攻略)

    写在前面的话 笔者从17年的2月份开始准备春招,其中遇到不少坑,也意识到自己走过的弯路.故写了这篇文章总结一番,本文适合主动学习的,对自己要学的课程不明确的,对面试有恐惧症的...等将来打算从事技术岗 ...

  2. api-gateway实践(15)3.6JL分支和3.7并行改造需求

    一.名称改为"API网关" --哪个地方的名称?二.开发者视图中,API网关显示两个视图. 1. 服务分类视图:支持按照业务分为多个类别,分类方式参照应用服务化的分类:人像比对.自 ...

  3. 关于阿里巴巴iconfont的使用方法

    iconfont网址:http://www.iconfont.cn/ 说起iconfont,做前端开发的应该知道它的好处,图标库之丰富,只有你想不到的,没有你找不到的,而且轻量高清.用户在iconfo ...

  4. C# 客户端程序调用外部程序的三种实现

    简介 我们用C#来开发客户端程序的时候,总会不可避免的需要调用外部程序或者访问网站,本篇博客介绍了三种调用外部应用的方法,供参考 实现 第一种是利用shell32.dll,实现ShellExecute ...

  5. java集合小知识的复习

    *Map接口 Map<k,v>接口中接收两个泛型,key和value的两个数据类型 Map中的集合中的元素都是成对存在的每个元素由键与值两部分组成,通过键可以找对所对应的值.值可以重复,键 ...

  6. Django ORM创建数据库

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...

  7. Windows10下的docker安装与入门 (二)使用docker引擎在容器中运行镜像

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...

  8. Java基础语法<十> Jar文件

    1 JAR文件            java归档文件,压缩的            jdk/bin jar工具制作jar文件              jar程序选项 1.1清单文件         ...

  9. Effective Java 第三版——38. 使用接口模拟可扩展的枚举

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  10. Java知识体系纲要

    最近一段时间,把Java主要涉及到的大概念都大致学习了一遍,为了让自己能够更好地形成对Java知识体系的整体把握,先把学过的知识点添加到自己画的思维导图上. 整个Java知识体系的划分,我自己主要将它 ...