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. restful架构风格设计准则(二)以资源为中心,一个url

    读书笔记,原文链接:http://www.cnblogs.com/loveis715/p/4669091.html,感谢作者! 1.REST是一种架构风格,其核心是面向资源,简化设计,降低开发的复杂性 ...

  2. EasyUI combobox下拉多选框的实现

    combobox实现下拉列表多选, 效果如下

  3. webservice面试题

    webservice是什么? 1.基于WEB的服务,服务端整出一些资源让客户端应用访问(提供数据) 2.webservice是一个跨语言跨平台的规范(抽象) 3.是多个跨语言跨平台的应用间通信整合的方 ...

  4. Struts(二十一):类型转换与复杂属性、集合属性配合使用

    背景: 本章节主要以复杂属性.集合属性类型转化为例,来学习这两种情况下怎么使用. 复杂对象属性转换场景: 1.新建struts_04 web.xml <?xml version="1. ...

  5. 南京邮电大学java第二次实验报告

    实 验 报 告 ( 2017 / 2018学年 第2学期) 课程名称 JAVA语言程序设计 实验名称 Java集成开发环境的安装与使用. Java变量.表达式与控制结构 实验时间 2018 年 4 月 ...

  6. hdu-2639 Bone Collector II---第k大背包

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2639 题目大意: 求第k大背包. 思路: 由01背包递推式dp[i][j] = max(dp[i][ ...

  7. Spring MVC的核心流程(步骤)

    具体步骤: 1.客户端发送请求先要经过前端控制器,请求被Spring 前端控制器DispatcherServlet获取,如详细图第一步:DispatcherServlet对请求URL进行解析(比如我们 ...

  8. 如何彻底解决MySQL更改默认字符集以及字符乱码问题!!!

    在我们使用MySQL数据库时,字符乱码,对我们来说是一个很头疼的问题.今天笔者就来教大家如何彻底解决更改默认字符集以及字符乱码问题. 当我们使用压缩包进行MySQL安装后,系统会使用默认的字符集,这时 ...

  9. 常见web安全隐患及解决方案

    Abstract 有关于WEB服务以及web应用的一些安全隐患总结资料. 1. 常见web安全隐患 1.1.       完全信赖用户提交内容 开发人员决不能相信一个来自外部的数据.不管它来自用户提交 ...

  10. ios开发- 利用运行时(runtime)字典转模型

    现在的ios开发中,我们通常会使用MVC模式.当我们拿到数据的时候,我们要把数据转成模型使用. 一般情况我们拿到的数据都是字典.这是我们就需要将字典转成模型对象了. 当对象的属性很少的时候,我们可以直 ...