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. Spring AOP AspectJ

    本文讲述使用AspectJ框架实现Spring AOP. 再重复一下Spring AOP中的三个概念, Advice:向程序内部注入的代码. Pointcut:注入Advice的位置,切入点,一般为某 ...

  2. kubernetes入门(10)kubernetes单机安装后 - helloworld

    前言 查看端口是否被监听了 ::netstat -tlp |grep 31002 我是用的yum install etcd kubernetes docker vim, 这样装的是1.5.2,不是最新 ...

  3. Extensions in UWP Community Toolkit - SurfaceDialTextbox

    概述 UWP Community Toolkit Extensions 中有一个为TextBox 提供的 SurfaceDial 扩展 - SurfaceDialTextbox,本篇我们结合代码详细讲 ...

  4. POJ1236【Tarjan+缩点】

    题目大意:有向关系体现在电脑可以通过网络单向的传输文件,并规定一旦有电脑存在该文件,那么所有它能传输的电脑就能在第一时间得到这个文件,题目有两个问题,第一个是最少向网络中的几台电脑投放文件,能使得整个 ...

  5. Hibernate(十四):HQL查询(三)

    背景 基于上两章节<Hibernate(十二):HQL查询(一)>.<Hibernate(十三):HQL查询(二)>,已经学习了一部分关于HQL的用法: HQL带参数查询 HQ ...

  6. Thymeleaf3语法详解和实战

    Thymeleaf3语法详解 Thymeleaf是Spring boot推荐使用的模版引擎,除此之外常见的还有Freemarker和Jsp.Jsp应该是我们最早接触的模版引擎.而Freemarker工 ...

  7. 原生js的一些研究和总结(1)

    数据类型 基本类型值包括: undefined,null,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,它们的值保存在栈空间,我们通过按值来访问的. 引用类型包括 ...

  8. windows汇编环境配置

    原文地址 软件下载 需要的软件已经打包,包括dosbox和MASM.如果没有这两个软件可以在下面的地址下载. http://hjwblog.com/game/汇编环境.zip 点击下载 安装dosbo ...

  9. JavaScript数据结构与算法(五) 数组基础算法

  10. java中的强大的枚举(基本没人用)

    枚举的概念和多例设计模式相似,多例设计模式详见:多例设计模式代码模型 范例:简单枚举类 通过emu关键字定义一个枚举 package com.java.demo; enum Color{ RED,BL ...