辽宁自考 Java语言程序设计 课程代码 01019 备考整理(五)

Java语言程序设计

考试用书: 《Java语言程序设计》(第三版)
出版社:清华大学出版社
作者:邵丽萍、绍光亚、张后扬
出版时间:2008

第10章 多线程机制

多线程的概念

程序、进程、多任务
  1. 程序:程序是数据描述与操作代码的集合,是应用程序执行的脚本。
  2. 进程:进程是程序的一次执行过程,是操作系统运行程序的基本单位。系统运行一个程序是一个进程从创建、运行到消亡的过程。操作系统可以为一个程序同时创建多个进程。
  3. 多任务:多任务是指在一个系统中可以同时运行多个程序,即有多个独立运行的任务,每一个任务对应一个进程。由于一个CPU在同一时刻只能执行一个程序中的一条指令。实际上,多任务运行的并发机制使这些任务交替运行,因间隔时间短,所以你感觉就是多个程序在同时运行。如果是多个CPU,可以同时执行多个任务。
线程

(运行一个程序时,程序内部的代码都是按顺序先后执行的。如果能够将一个进程划分为更小的运行单位,则程序中一些彼此相对独立的代码段可以重叠运行,将会获得更高的执行效率。线程就是解决这个问题的。)
线程是一种特殊的多任务方式。当一个程序执行多线程时,可以运行两个或更多的由同一个程序启动的任务。
线程也有开始、执行、结束三个部分。
线程与程序不同的是线程本身不能运行,它只能包含在程序中,只能在程序中执行。
一个线程在程序运行时,必须争取到为自己分配的系统资源,如执行堆栈、程序计数器等。

多线程

多线程是相对于单线程而言的,指的是在一个程序中可以定义多个线程并同时运行它们,每个线程执行不同的任务。与进程不同的是同类多线程共享一块内存空间和一组系统资源,所以系统创建线程花费代价较小。因此也称线程为轻负荷进程。
多线程和多任务是两个既有联系又有区别的概念,多任务是针对操作系统而言的,代表操作系统可以同时执行程序的个数,多线程是针对一个程序而言的,代表一个程序内部可以同时执行的线程个数。

线程的生命周期与Java的多线程机制

(1)创建(new)阶段:使用new操作符创建并初始化线程对象后,此时线程已经分配到内存空间和所需要的资源。
(2)可以运行(runable)阶段:在使用线程对象的start方法后,进入线程队列,排队等待CPU的使用权,一旦获得CPU的使用权,就开始独立运行。
(3)在运行(running)阶段:获得CPU使用权后,正在执行线程对线的run方法。
(4)挂起(not runable)阶段:一个正在执行的线程对象,因为某种特殊原因或需要执行输入输出操作时,将让出CPU的使用权,线程进入挂起状态。挂起的线程不能加入CPU等候队列。必须等到挂起原因消除后,才可以去排队。
(5)死亡(dead)阶段:线程执行run方法最后一句并退出,或线程被强制死亡,即使用stop方法与destroy方法。

Java的每个程序自动拥有一个线程,成为主线程。当程序加载到内存时,启动主线程。要加载其它进程需要使用Thread类和Runable接口。
java.lang 包中的Thread类封装了所有需要的线程操作控制用来控制线程的声明周期,这就是Java的多线程机制。

创建线程对象

有两种方法可以创建线程对象,一种是通过继承线程类Thread来创建线程对象,一种是实现Runable接口来创建线程对象。

通过继承Thread来创建线程对象
class 线程类名 extends Thread {
	public void run(){
		程序语句...
	}
}

//执行的时候使用的是 线程类名.start(); 而不是线程类名.run 这是考点。
通过Runable接口创建线程对象
public class TestMain {

    private static class RunableThread implements Runnable {

        private String name;

        public RunableThread(String name){
            this.name = name;
        }

        public void run() {
            for(int i = 0 ; i < 100 ; i++){
                System.out.println(this.name);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String args[]){
        Thread thread1 = new Thread(new RunableThread("线程1"));
        Thread thread2 = new Thread(new RunableThread("线程2"));
        thread1.start();
        thread2.start();
    }
}

Thread 本质也是实现了runable接口。而实现了runable接口的类也必须通过Thread运行。

两种创建线程方法的比较

(1)继承Thread类创建线程对象简单方便,可以直接操作线程,但不能再继承其它类。
(2)在继承其它类的类中用Runable接口创建线程对象,可以保持程序风格的一致性。

线程的优先级

线程在创建时继承了父类的优先级。线程创建后,还可以在任何时刻调用setPriority方法改变线程优先级。优先级为1~10,Thread中定义了三个常数:
(1)MAX_PRIORITY,最大优先级(值为10)。
(1)MIN_PRIORITY,最小优先级(值为1)。
(1)NORM_PRIORITY,默认优先级(值为5)。

线程的调度与控制

线程方法
//线程类方法
Thread.CurrentThread(); //返回正在运行的Thead对象名称。
Thread.sleep(int n); //让当前线程休眠n毫秒。
//线程类实例方法
实例.activeCount(); //返回线程组中激活的线程数目
实例.checkAccess(); //检测当前线程是否可以被修改
实例.destroy(); //终止线程,不清除其它相关内容
实例.getName(); //返回线程名称
实例.getPriority(); //返回线程优先级
实例.interrupt(); //向线程发送中断信息
实例.interrupted(); //检测线程是否已经中断
实例.isAlive(); //检测线程是否处于激活状态
实例.isDaemon(); //检测线程是否常驻内存
实例.isInterrupted(); //检测另一个线程是否已经中断
实例.join(long); //中止当前线程,等待long毫秒,调用该线程的方法完成后再继续本线程。
实例.join(long,int); //中止当前线程,等待long毫秒,int纳秒,中止调用该方法的线程。
实例.join(); //中止当前线程,直到调用该线程方法完成后再继续本线程。
// join  A.Join() 意义就是 A这个线程执行完再执行 调用A.join的线程。
实例.resume(); //重新开始执行本线程。
实例.run(); //线程入口。
实例.setDaemon(); //将线程设置为Daemon(常驻内存)。
实例.setName(String); //设置线程名称。
实例.setPriority(int); //设置线程优先级。
实例.sleep(long); //设置线程休眠long毫秒。
实例.sleep(long,int); //设置线程休眠long毫秒,int纳秒。
实例.start(); //启动一个线程,线程会自动调用run方法,在新的线程开始执行的同时,调用start()的那个线程将立即返回执行主线程。
实例.stop(); //终止一个线程。
实例.stop(Throwable); //终止一个线程,该线程是由Throwable继承过来的。
实例.suspend(); //暂停线程的执行。
实例.toString(); //返回一个代表线程的字符串。
实例.yield(); //挂起当前线程,使其他处于等待状态的线程运行。

suspend()与resume()是一对的。suspend暂停,resume继续。
stop()用来停止线程,但是线程并不能再通过start()启动。
sleep(long)用来休眠当前线程。
join() 可以中止当前线程,等待join中的线程执行完毕后再执行。原书中,写的不太容易理解。
但是如果要考试一定要用书中的方式回答。中止当前线程,调用该线程的方法执行完毕后再继续本线程。
yield()暂停线程,使其它线程运行,如果没有运行的其它线程,则线程继续运行。
interrupt()中断线程,可通过start()重新启动线程。
isAlive()方法返回true说明线程处于runable或者notrunable状态。如果返回值为false则线程处于newThread 或 dead状态。

Java的线程同步机制与生产消费模型

public class Share {
    private int u;
    private boolean available=false;

    public synchronized int get(){
        while (available == false){
            try {
                wait();
            }catch (InterruptedException e){}
        }
        available = false;
        notifyAll();
        return u;
    }
    public synchronized void put(int value){
        while (available==true){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        u=value;
        available=true;
        notifyAll();
    }
}
------------------------------------------------------------------------
public class Consumer extends Thread {
    private Share shared;
    public Consumer(Share s){
        this.shared = s;
    }

    public void run(){
        int value = 0;
        for(int i = 0;i< 10 ;i++){
            value = shared.get();
            System.out.println("消费者" + " 拿到的生产数据为:" + value);
        }
    }
}
-------------------------------------------------------------------------
public class Producer extends Thread{
    private Share shared;

    public Producer(Share s){
        this.shared = s;
    }

    public void run(){
        for(int i = 0;i<10;i++){
            shared.put(i);
            System.out.println("生产者:" + " 的生产数据为:" + i);
            try {
                sleep((int)(Math.random()*100));
            }catch (InterruptedException e){}
        }
    }
}
--------------------------------------------------------------------------
public class PCmx {
    public static void main(String args[]){
        Share s = new Share();
        Producer p = new Producer(s);
        Consumer c = new Consumer(s);
        p.start();
        c.start();
    }
}

除了以上方法之外还可以给变量加 synchronized(变量名) 来锁定变量。同一时间只能有一个线程访问锁定的共享资源,只有在线程获得锁定的共享资源后,才可以运行。

使用多线程应注意的问题

(1)线程需要占用内存。
(2)线程过多,会消耗大量CPU时间来跟踪线程。
(3)必须考虑多线程同时访问共享资源的问题,如果没有协调好会产生死锁和资源竞争。
(4)因为同一个任务的所有线程都共享相同的地址空间,并共享任务的全局变量,所以程序也必须考虑多线程同时访问全局变量的问题。

在这里插入图片描述

第11章图形多媒体处理

使用Graphics绘制基本图形

图形必须绘制在画板上,面板主要包括:面板(Panel或JPanel类)、窗口(Frame或JFrame类)、Java Applet小程序窗口以及画布(Canvas)类。
图形的颜色使用Java提供的Color类。
绘图用的画笔使用Java提供的Graphics类与Graphics2D类。

Color类内置了多个颜色常量可以直接使用。例如Color.red //红色
也可以通过构造方法
Color(float r, float g, float b) //使用单个RGB的浮点类型值
Color(int r, int g, int b) //使用单个RGB的整数类型值
Color(int rgb) //使用RGB的混合整数值

import javax.swing.*;
import java.awt.*;

public class Rectangles extends JFrame {
    public Rectangles (){
        super("绘制矩形窗口");
        setSize(500,200);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.red);
        g.drawRect(20,30,80,80);
        g.fillRect(120,30,80,80);
        g.drawRoundRect(220,30,80,80,20,20);
        g.fillRoundRect(320,30,80,80,20,20);

        int i, x1, y1, x2, y2;
        for(i = 1;i<=10;i++){
            x1 = (int)(Math.random()*10);
            y1 = (int)(Math.random()*200);
            x2 = (int)(Math.random()*380);
            y2 = (int)(Math.random()*200);
            g.drawLine(x1,y1,x2,y2);
        }
    }

    public static void main(String args[]){
        Rectangles d = new Rectangles();
    }
}

使用Graphics2D绘制基本图形

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;

public class DrawRect2D extends JFrame {
    public DrawRect2D (){
        super("绘制矩形窗口");
        setSize(500,200);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setPaint(Color.black);
        g2d.setStroke(new BasicStroke(3.0f));
        g2d.draw(new Rectangle2D.Double(10, 50, 80, 60));
        g2d.setPaint(Color.blue);
        g2d.fill(new Rectangle2D.Double(100, 50 ,80,60));

    }

    public static void main(String args[]){
        DrawRect2D d = new DrawRect2D();
    }
}

使用Graphics绘制文字图形

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;

public class ZF1 extends JFrame {

    String s = "This is a string";
    char c[] = {'这','是','一','个','字','符','数','组'};
    byte b[] = {97,' ','b','y','t','e',' ',97,114,114,97,121};

    public ZF1(){
        super("绘制矩形窗口");
        setSize(500,200);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.ORANGE);
        g.setFont(new Font("SansSerif",Font.BOLD,24));
        g.drawString(s,30,60);
        g.drawChars(c,0,8,30,90);
        g.drawBytes(b,0,12,30,120);
    }

    public static void main(String args[]){
        ZF1 d = new ZF1();
    }
}

图像处理

Image img = new Image();
img.set
g.drawImage(new Image("图形路径"),宽度,高度,this); 
import javax.swing.*;
import java.awt.*;

public class ZF1 extends JFrame {

    String s = "This is a string";
    char c[] = {'这','是','一','个','字','符','数','组'};
    byte b[] = {97,' ','b','y','t','e',' ',97,114,114,97,121};
    Image img;
    Toolkit toolkit;

    public ZF1(){
        super("绘制矩形窗口");
        setSize(500,200);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        toolkit = getToolkit();
        img = toolkit.getImage("C:\\Users\\LiuJinYan\\Desktop\\483183-20180829092510311-1546229320.png");
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.ORANGE);
        g.setFont(new Font("SansSerif",Font.BOLD,24));
        g.drawString(s,30,60);
        g.drawChars(c,0,8,30,90);
        g.drawBytes(b,0,12,30,120);
        g.drawImage(img,30,150,200,200,this);
    }

    public static void main(String args[]){
        ZF1 d = new ZF1();
    }
}

动画

在paint绘制方法中不断的调用repaint重绘来实现动画效果。也可以在外部的循环方法中不断的调用paint绘制方法来完成动画。

加载声音文件

import javax.swing.*;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

public class DMT6 extends Applet implements ItemListener, ActionListener {

AudioClip sound;
JButton play = new JButton("播放");
JButton loop = new JButton("连续");
JButton stop = new JButton("停止");
JComboBox xx;
private String names[] = {"notify.wav","camptown.mid","betsy.mid"};

public DMT6 (){
    xx = new JComboBox(names);
    add(xx);
    xx.addItemListener(this);
    add(play);
    add(loop);
    add(stop);
    play.addActionListener(this);
    stop.addActionListener(this);
    loop.addActionListener(this);
    sound = getAudioClip(getCodeBase(),"音乐/"+"notify.wav");

}

@Override
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == play){
        sound.play();
    }else if(e.getSource() == loop){
        sound.loop();
    }else if(e.getSource() == stop){
        sound.stop();
    }
}

@Override
public void itemStateChanged(ItemEvent e) {
    sound.stop();
    sound = getAudioClip(getCodeBase(),"音乐/"+ xx.getSelectedItem());
}

}

访问数据库

SQL语句

略 增删改查等语句见数据库原理与应用备考

通过Java访问数据库

书中给出的例子是通过windows操作系统自带的ODB管理模块来配置数据库的访问,然后Java通过JDBC连接ODBC再与数据库进行连接。
Java1.8已经默认移除了ODBC相关的库,所以要想成功访问需要使用Java1.7及以下的版本。

import java.sql.*;

public class DBxc {
    public static void main(String args[]) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            conn = DriverManager.getConnection("jdbc:odbc:odbc定义名","数据库用户名","数据库密码");
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            stmt = (Statement) conn.createStatement();
            String sql = "select snum,sname from student";
            rs=stmt.executeQuery(sql);
            while (rs.next()){
                long xh = rs.getLong(1);
                String xm = rs.getString(2);
                System.out.print("学号:" + xh);
                System.out.println("姓名: " + xm);
            }
            rs.close();
            stmt.close();
            conn.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}
连接数据库与查询数据的过程

(1)引入SQL类包: import java.sql.*;
(2)装载并注册驱动程序Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
(3)创建与数据库建立连接的Connection 对象 Connection conn = DriverManager.getConnection("jdbc:odbc:odbc定义名","数据库用户名","数据库密码");
(4)创建SQL执行语句的Statement对象与ResultSet对象

Statement stmt = (Statement) conn.createStatement();
ResultSet rs=stmt.executeQuery(sql);

(5)释放资源

 rs.close();
 stmt.close();
 conn.close();
添加和更新数据的过程
String sql = "insert into sc(snum,cnum,grade)  values (29,?,?)"
PreparedStatement ps = (PreparedStatement) conn.prepareStatement(sql);
ps.setInt(1,12);  //设置第一个参数为int 类型 值为12
ps.setFloat(2,90); //设置第二个参数为Float类型 值为90
ps.executeUpdate(); //执行更新 Update和Insert都执行executeUpdate
//这块的重要理解是 可以通过在sql中添加?符号来设置参数的位置,并通过PreparedStatement 来设置参数的实际值。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值